提交 476abd12 编写于 作者: Q Quleaf

update to v2.0.0

上级 4208c1da
...@@ -33,7 +33,7 @@ English | [简体中文](README_CN.md) ...@@ -33,7 +33,7 @@ English | [简体中文](README_CN.md)
</a> </a>
<!-- PyPI --> <!-- PyPI -->
<a href="https://pypi.org/project/paddle-quantum/"> <a href="https://pypi.org/project/paddle-quantum/">
<img src="https://img.shields.io/badge/pypi-v1.2.0-orange.svg?style=flat-square&logo=pypi"/> <img src="https://img.shields.io/badge/pypi-v2.0.0-orange.svg?style=flat-square&logo=pypi"/>
</a> </a>
<!-- Python --> <!-- Python -->
<a href="https://www.python.org/"> <a href="https://www.python.org/">
...@@ -71,7 +71,7 @@ Paddle Quantum aims at establishing a bridge between artificial intelligence (AI ...@@ -71,7 +71,7 @@ Paddle Quantum aims at establishing a bridge between artificial intelligence (AI
### Install PaddlePaddle ### Install PaddlePaddle
This dependency will be automatically satisfied when users install Paddle Quantum. Please refer to [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick)'s official installation and configuration page. This project requires PaddlePaddle 1.8.5. This dependency will be automatically satisfied when users install Paddle Quantum. Please refer to [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick)'s official installation and configuration page. This project requires PaddlePaddle 2.0.1+.
### Install Paddle Quantum ### Install Paddle Quantum
...@@ -96,8 +96,8 @@ pip install -e . ...@@ -96,8 +96,8 @@ pip install -e .
Once the user confirms the above OS constraint, OpenFermion can be installed with the following command. These packages are used for quantum chemistry calculations and could be potentially used in the VQE tutorial. Once the user confirms the above OS constraint, OpenFermion can be installed with the following command. These packages are used for quantum chemistry calculations and could be potentially used in the VQE tutorial.
```bash ```bash
pip install openfermion==0.11.0 pip install openfermion
pip install openfermionpyscf==0.4 pip install openfermionpyscf
``` ```
### Run example ### Run example
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
</a> </a>
<!-- PyPI --> <!-- PyPI -->
<a href="https://pypi.org/project/paddle-quantum/"> <a href="https://pypi.org/project/paddle-quantum/">
<img src="https://img.shields.io/badge/pypi-v1.2.0-orange.svg?style=flat-square&logo=pypi"/> <img src="https://img.shields.io/badge/pypi-v2.0.0-orange.svg?style=flat-square&logo=pypi"/>
</a> </a>
<!-- Python --> <!-- Python -->
<a href="https://www.python.org/"> <a href="https://www.python.org/">
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
### 安装 PaddlePaddle ### 安装 PaddlePaddle
当用户安装 Paddle Quantum 时会自动下载安装这个关键依赖包。关于 PaddlePaddle 更全面的安装信息请参考 [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick) 安装配置页面。此项目需求 PaddlePaddle 1.8.5 当用户安装 Paddle Quantum 时会自动下载安装这个关键依赖包。关于 PaddlePaddle 更全面的安装信息请参考 [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick) 安装配置页面。此项目需求 PaddlePaddle 2.0.1+
### 安装 Paddle Quantum ### 安装 Paddle Quantum
...@@ -95,8 +95,8 @@ pip install -e . ...@@ -95,8 +95,8 @@ pip install -e .
VQE中调用 OpenFermion 读取分子 .xyz 文件并计算,因此需要安装 openfermion 和 openfermionpyscf。 VQE中调用 OpenFermion 读取分子 .xyz 文件并计算,因此需要安装 openfermion 和 openfermionpyscf。
```bash ```bash
pip install openfermion==0.11.0 pip install openfermion
pip install openfermionpyscf==0.4 pip install openfermionpyscf
``` ```
### 运行 ### 运行
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
"\n", "\n",
"这里,我们介绍如何在 x64 平台上的 Windows10 系统中配置 CUDA 环境。首先,在[CUDA GPUs | NVIDIA Developer](https://developer.nvidia.com/cuda-gpus)上查看你的GPU是否可以安装CUDA环境。然后,在[NVIDIA 驱动程序下载](https://www.nvidia.cn/Download/index.aspx?lang=cn)下载你的显卡的最新版驱动,并安装到电脑上。\n", "这里,我们介绍如何在 x64 平台上的 Windows10 系统中配置 CUDA 环境。首先,在[CUDA GPUs | NVIDIA Developer](https://developer.nvidia.com/cuda-gpus)上查看你的GPU是否可以安装CUDA环境。然后,在[NVIDIA 驱动程序下载](https://www.nvidia.cn/Download/index.aspx?lang=cn)下载你的显卡的最新版驱动,并安装到电脑上。\n",
"\n", "\n",
"在[飞桨的安装步骤](https://www.paddlepaddle.org.cn/install/quick)中,我们发现,**Paddle Paddle 在 Windows 下仅支持 CUDA 9.0/10.0 的单卡模式;不支持 CUDA 9.1/9.2/10.1**,所以,我们需要安装 CUDA10.0(CUDA9.0在理论上也可以)。在[CUDA Toolkit Archive | NVIDIA Developer](https://developer.nvidia.com/cuda-toolkit-archive)找到 CUDA 10.0 的下载地址:[CUDA Toolkit 10.0 Archive | NVIDIA Developer](https://developer.nvidia.com/cuda-10.0-download-archive),下载CUDA后,运行安装。\n", "在[飞桨的安装步骤](https://www.paddlepaddle.org.cn/install/quick)中,我们发现,**PaddlePaddle 的 GPU版本支持CUDA 9.0/10.0/10.1/10.2/11.0,且仅支持单卡**。所以这里,我们安装 CUDA10.2。在[CUDA Toolkit Archive | NVIDIA Developer](https://developer.nvidia.com/cuda-toolkit-archive)找到 CUDA 10.2 的下载地址:[CUDA Toolkit 10.2 Archive | NVIDIA Developer](https://developer.nvidia.com/cuda-10.2-download-archive),下载CUDA后,运行安装。\n",
"\n", "\n",
"在安装过程中,选择**自定义安装**,在 CUDA 选项中,勾选除 Visual Studio Intergration 外的其他内容(除非你理解 Visual Studio Intergration 的作用),然后除 CUDA 之外,其他选项均不勾选。然后安装位置选择默认位置(请留意你的 CUDA 的安装位置,后面需要设置环境变量),等待安装完成。\n", "在安装过程中,选择**自定义安装**,在 CUDA 选项中,勾选除 Visual Studio Intergration 外的其他内容(除非你理解 Visual Studio Intergration 的作用),然后除 CUDA 之外,其他选项均不勾选。然后安装位置选择默认位置(请留意你的 CUDA 的安装位置,后面需要设置环境变量),等待安装完成。\n",
"\n", "\n",
...@@ -43,18 +43,18 @@ ...@@ -43,18 +43,18 @@
"\n", "\n",
"### 安装 cuDNN\n", "### 安装 cuDNN\n",
"\n", "\n",
"在[NVIDIA cuDNN | NVIDIA Developer](https://developer.nvidia.com/cudnn)下载 cuDNN,根据[飞桨的安装步骤](https://www.paddlepaddle.org.cn/install/quick)中的要求,我们**需要使用 cuDNN 7.6+** ,因此我们下载支持 CUDA 10.0 的最新版 cuDNN 即可。下载完成 cuDNN 后进行解压缩。然后,假设我们的 CUDA 的安装路径为`C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0`,我们将 cuDNN 解压缩后里面的`bin`、`include`和`lib`中的文件都替换 CUDA 的安装路径下的对应文件(如果文件已存在则进行替换,如果未存在则直接粘贴到对应目录中)。到这里,cuDNN 也就安装完成了。\n", "在[NVIDIA cuDNN | NVIDIA Developer](https://developer.nvidia.com/cudnn)下载 cuDNN,根据[飞桨的安装步骤](https://www.paddlepaddle.org.cn/install/quick)中的要求,我们**需要使用 cuDNN 7.6.5+** ,因此我们下载支持 CUDA 10.2 的 7.6.5 版 cuDNN 即可。下载完成 cuDNN 后进行解压缩。然后,假设我们的 CUDA 的安装路径为`C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2`,我们将 cuDNN 解压缩后里面的`bin`、`include`和`lib`中的文件都替换 CUDA 的安装路径下的对应文件(如果文件已存在则进行替换,如果未存在则直接粘贴到对应目录中)。到这里,cuDNN 也就安装完成了。\n",
"\n", "\n",
"\n", "\n",
"### 配置环境变量\n", "### 配置环境变量\n",
"\n", "\n",
"接下来还需要配置环境变量。右键电脑桌面上的“此电脑”(或“文件资源管理器”左栏的“此电脑”),选择“属性”,然后选择左侧的“高级系统设置”,在“高级”这一栏下选择“环境变量”。\n", "接下来还需要配置环境变量。右键电脑桌面上的“此电脑”(或“文件资源管理器”左栏的“此电脑”),选择“属性”,然后选择左侧的“高级系统设置”,在“高级”这一栏下选择“环境变量”。\n",
"\n", "\n",
"现在就进入到了环境变量的设置页面,在系统变量中选择`Path`,点击“编辑”。在出现的页面中,查看是否有`C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0\\bin`和`C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0\\libnvvp`这两个地址(其前缀`C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0`应该为你的 CUDA 的安装位置),如果没有,请手动添加。\n", "现在就进入到了环境变量的设置页面,在系统变量中选择`Path`,点击“编辑”。在出现的页面中,查看是否有`C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\\bin`和`C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\\libnvvp`这两个地址(其前缀`C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2`应该为你的 CUDA 的安装位置),如果没有,请手动添加。\n",
"\n", "\n",
"### 验证是否安装成功\n", "### 验证是否安装成功\n",
"\n", "\n",
"打开命令行,输入`cd C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0\\extras\\demo_suite`进入到 CUDA 安装路径(这里也应该为你的 CUDA 的安装位置)。然后分别执行`.\\bandwidthTest.exe`和`.\\deviceQuery.exe`,如果都出现`Result = PASS`,则说明安装成功。\n", "打开命令行,输入`cd C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\\extras\\demo_suite`进入到 CUDA 安装路径(这里也应该为你的 CUDA 的安装位置)。然后分别执行`.\\bandwidthTest.exe`和`.\\deviceQuery.exe`,如果都出现`Result = PASS`,则说明安装成功。\n",
"\n" "\n"
] ]
}, },
...@@ -64,13 +64,13 @@ ...@@ -64,13 +64,13 @@
"source": [ "source": [
"## 在 CUDA 环境上安装 PaddlePaddle\n", "## 在 CUDA 环境上安装 PaddlePaddle\n",
"\n", "\n",
"根据[飞桨的安装步骤](https://www.paddlepaddle.org.cn/install/quick)中的说明,我们首先需要确定自己的python环境,用`python --version`来查看 python 版本,保证**python版本是3.5.1+/3.6+/3.7+**,并且用`python -m ensurepip`和`python -m pip --version`来查看 pip 版本,**确认是 9.0.1+**。然后,使用`python -m pip install paddlepaddle-gpu==1.8.4.post107 -i https://pypi.tuna.tsinghua.edu.cn/simple`来安装 GPU 版本的 PaddlePaddle。\n", "根据[飞桨的安装步骤](https://www.paddlepaddle.org.cn/install/quick)中的说明,我们首先需要确定自己的python环境,用`python --version`来查看 python 版本,保证**python版本是3.5.1+/3.6+/3.7/3.8**,并且用`python -m ensurepip`和`python -m pip --version`来查看 pip 版本,**确认是 20.2.2+**。然后,使用`python -m pip install paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple`来安装 GPU 版本的 PaddlePaddle。\n",
"\n", "\n",
"## 安装 Paddle Quantum\n", "## 安装 Paddle Quantum\n",
"\n", "\n",
"下载 Paddle Quantum 的安装包,修改`setup.py`,将其中的`paddlepaddle`改为`paddlepaddle-gpu`,然后按照 Paddle Quantum 的安装要求,执行`pip install -e .`即可。\n", "下载 Paddle Quantum 的安装包,修改`setup.py`和`requirements.txt`,将其中的`paddlepaddle`改为`paddlepaddle-gpu`,然后按照 Paddle Quantum 的从源代码安装的要求,执行`pip install -e .`即可。\n",
"\n", "\n",
"> 如果你是在一个新的 python 环境中安装了 paddlepaddle-gpu 和 paddle_quantum,请在新 python 环境中安装 jupyter,并在新的 jupyter 下重新打开本教程并运行。\n", "> 如果你是在一个新的 python 环境中安装了 paddlepaddle-gpu 和 paddle_quantum,请在新 python 环境中安装 jupyter,并在新的 jupyter 下重新打开本教程并运行。\n",
"\n", "\n",
"## 检测是否安装成功\n", "## 检测是否安装成功\n",
"\n", "\n",
...@@ -91,9 +91,8 @@ ...@@ -91,9 +91,8 @@
} }
], ],
"source": [ "source": [
"import paddle \n", "import paddle\n",
"from paddle import fluid\n", "print(paddle.is_compiled_with_cuda())"
"print(fluid.is_compiled_with_cuda())"
] ]
}, },
{ {
...@@ -111,9 +110,8 @@ ...@@ -111,9 +110,8 @@
"source": [ "source": [
"```python\n", "```python\n",
"# 0 表示使用编号为0的GPU\n", "# 0 表示使用编号为0的GPU\n",
"place = fluid.CUDAPlace(0)\n", "paddle.set_device(\"gpu:0\")\n",
"with fluid.dygraph.guard(place):\n", "# build and train your quantum circuit model\n",
" # build and train your quantum circuit model\n",
"```" "```"
] ]
}, },
...@@ -129,9 +127,8 @@ ...@@ -129,9 +127,8 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"```python\n", "```python\n",
"place = fluid.CPUPlace()\n", "paddle.set_device(\"cpu\")\n",
"with fluid.dygraph.guard(place):\n", "# build and train your quantum circuit model\n",
" # build and train your quantum circuit model\n",
"```" "```"
] ]
}, },
...@@ -151,17 +148,40 @@ ...@@ -151,17 +148,40 @@
"outputs": [], "outputs": [],
"source": [ "source": [
"import os\n", "import os\n",
"import numpy\n",
"from numpy import concatenate\n", "from numpy import concatenate\n",
"from numpy import pi as PI\n", "from numpy import pi as PI\n",
"from numpy import savez, zeros\n", "from numpy import savez, zeros\n",
"from paddle import fluid\n", "from paddle import matmul, transpose\n",
"from paddle.complex import matmul, transpose\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"\n", "\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"import numpy\n", "import numpy\n",
"from paddle_quantum.VQE.chemistrysub import H2_generator\n", "\n",
"from time import time\n", "\n",
"def H2_generator():\n",
" \n",
" H = [\n",
" [-0.04207897647782277, 'i0'],\n",
" [0.17771287465139946, 'z0'],\n",
" [0.1777128746513994, 'z1'],\n",
" [-0.2427428051314046, 'z2'],\n",
" [-0.24274280513140462, 'z3'],\n",
" [0.17059738328801055, 'z0,z1'],\n",
" [0.04475014401535163, 'y0,x1,x2,y3'],\n",
" [-0.04475014401535163, 'y0,y1,x2,x3'],\n",
" [-0.04475014401535163, 'x0,x1,y2,y3'],\n",
" [0.04475014401535163, 'x0,y1,y2,x3'],\n",
" [0.12293305056183797, 'z0,z2'],\n",
" [0.1676831945771896, 'z0,z3'],\n",
" [0.1676831945771896, 'z1,z2'],\n",
" [0.12293305056183797, 'z1,z3'],\n",
" [0.1762764080431959, 'z2,z3']\n",
" ]\n",
" N = 4\n",
" \n",
" return H, N\n",
"\n",
"\n", "\n",
"Hamiltonian, N = H2_generator()\n", "Hamiltonian, N = H2_generator()\n",
"\n", "\n",
...@@ -190,18 +210,20 @@ ...@@ -190,18 +210,20 @@
" return expectation_val\n", " return expectation_val\n",
"\n", "\n",
"\n", "\n",
"class StateNet(fluid.dygraph.Layer):\n", "class StateNet(paddle.nn.Layer):\n",
" \"\"\"\n", " \"\"\"\n",
" Construct the model net\n", " Construct the model net\n",
" \"\"\"\n", " \"\"\"\n",
"\n", "\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " def __init__(self, shape, dtype=\"float64\"):\n",
" low=0.0, high=2 * PI), dtype=\"float64\"):\n",
" super(StateNet, self).__init__()\n", " super(StateNet, self).__init__()\n",
"\n", "\n",
" # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n", " # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n",
" self.theta = self.create_parameter(\n", " self.theta = self.create_parameter(\n",
" shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " shape=shape,\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI), \n",
" dtype=dtype, \n",
" is_bias=False)\n",
"\n", "\n",
" # 定义损失函数和前向传播机制\n", " # 定义损失函数和前向传播机制\n",
" def forward(self, Hamiltonian, N, D):\n", " def forward(self, Hamiltonian, N, D):\n",
...@@ -231,54 +253,51 @@ ...@@ -231,54 +253,51 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 20 loss: -1.0599\n", "iter: 20 loss: -0.9686\n",
"iter: 20 Ground state energy: -1.0599 Ha\n", "iter: 20 Ground state energy: -0.9686 Ha\n",
"iter: 40 loss: -1.1229\n", "iter: 40 loss: -1.1056\n",
"iter: 40 Ground state energy: -1.1229 Ha\n", "iter: 40 Ground state energy: -1.1056 Ha\n",
"iter: 60 loss: -1.1347\n", "iter: 60 loss: -1.1235\n",
"iter: 60 Ground state energy: -1.1347 Ha\n", "iter: 60 Ground state energy: -1.1235 Ha\n",
"iter: 80 loss: -1.1359\n", "iter: 80 loss: -1.1317\n",
"iter: 80 Ground state energy: -1.1359 Ha\n" "iter: 80 Ground state energy: -1.1317 Ha\n"
] ]
} }
], ],
"source": [ "source": [
"# 0 表示使用编号为0的GPU\n", "# 0 表示使用编号为0的GPU\n",
"place_gpu = fluid.CUDAPlace(0)\n", "paddle.set_device(\"gpu:0\")\n",
"with fluid.dygraph.guard(place_gpu):\n",
" \n", " \n",
" # 确定网络的参数维度\n", "# 确定网络的参数维度\n",
" net = StateNet(shape=[D + 1, N, 1])\n", "net = StateNet(shape=[D + 1, N, 1])\n",
"\n", "\n",
" # 一般来说,我们利用Adam优化器来获得相对好的收敛\n", "# 一般来说,我们利用Adam优化器来获得相对好的收敛\n",
" # 当然你可以改成SGD或者是RMS prop.\n", "# 当然你可以改成SGD或者是RMSProp\n",
" opt = fluid.optimizer.AdamOptimizer(\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" learning_rate=LR, parameter_list=net.parameters())\n",
"\n", "\n",
" # 记录优化结果\n", "# 记录优化结果\n",
" summary_iter, summary_loss = [], []\n", "summary_iter, summary_loss = [], []\n",
"\n", "\n",
" # 优化循环\n", "# 优化循环\n",
" for itr in range(1, ITR + 1):\n", "for itr in range(1, ITR + 1):\n",
"\n", "\n",
" # 前向传播计算损失函数\n", " # 前向传播计算损失函数\n",
" loss = net(Hamiltonian, N, D)\n", " loss = net(Hamiltonian, N, D)\n",
"\n", "\n",
" # 在动态图机制下,反向传播极小化损失函数\n", " # 在动态图机制下,反向传播极小化损失函数\n",
" loss.backward()\n", " loss.backward()\n",
" opt.minimize(loss)\n", " opt.minimize(loss)\n",
" net.clear_gradients()\n", " opt.clear_grad()\n",
"\n", "\n",
" # 更新优化结果\n", " # 更新优化结果\n",
" summary_loss.append(loss.numpy())\n", " summary_loss.append(loss.numpy())\n",
" summary_iter.append(itr)\n", " summary_iter.append(itr)\n",
"\n", "\n",
" # 打印结果\n", " # 打印结果\n",
" if itr % 20 == 0:\n", " if itr % 20 == 0:\n",
" print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n", " print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n",
" print(\"iter:\", itr, \"Ground state energy:\", \n", " print(\"iter:\", itr, \"Ground state energy:\", \n",
" \"%.4f Ha\" % loss.numpy())\n", " \"%.4f Ha\" % loss.numpy())\n"
"\n"
] ]
}, },
{ {
...@@ -297,53 +316,51 @@ ...@@ -297,53 +316,51 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 20 loss: -1.0865\n", "iter: 20 loss: -1.1080\n",
"iter: 20 Ground state energy: -1.0865 Ha\n", "iter: 20 Ground state energy: -1.1080 Ha\n",
"iter: 40 loss: -1.1153\n", "iter: 40 loss: -1.1301\n",
"iter: 40 Ground state energy: -1.1153 Ha\n", "iter: 40 Ground state energy: -1.1301 Ha\n",
"iter: 60 loss: -1.1338\n", "iter: 60 loss: -1.1357\n",
"iter: 60 Ground state energy: -1.1338 Ha\n", "iter: 60 Ground state energy: -1.1357 Ha\n",
"iter: 80 loss: -1.1359\n", "iter: 80 loss: -1.1361\n",
"iter: 80 Ground state energy: -1.1359 Ha\n" "iter: 80 Ground state energy: -1.1361 Ha\n"
] ]
} }
], ],
"source": [ "source": [
"# 表示使用 CPU\n", "# 表示使用 CPU\n",
"place_cpu = fluid.CPUPlace()\n", "paddle.set_device(\"cpu\")\n",
"with fluid.dygraph.guard(place_cpu):\n",
" \n", " \n",
" # 确定网络的参数维度\n", "# 确定网络的参数维度\n",
" net = StateNet(shape=[D + 1, N, 1])\n", "net = StateNet(shape=[D + 1, N, 1])\n",
"\n", "\n",
" # 一般来说,我们利用Adam优化器来获得相对好的收敛\n", "# 一般来说,我们利用Adam优化器来获得相对好的收敛\n",
" # 当然你可以改成SGD或者是RMS prop.\n", "# 当然你可以改成SGD或者是RMSProp\n",
" opt = fluid.optimizer.AdamOptimizer(\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" learning_rate=LR, parameter_list=net.parameters())\n",
"\n", "\n",
" # 记录优化结果\n", "# 记录优化结果\n",
" summary_iter, summary_loss = [], []\n", "summary_iter, summary_loss = [], []\n",
"\n", "\n",
" # 优化循环\n", "# 优化循环\n",
" for itr in range(1, ITR + 1):\n", "for itr in range(1, ITR + 1):\n",
"\n", "\n",
" # 前向传播计算损失函数\n", " # 前向传播计算损失函数\n",
" loss = net(Hamiltonian, N, D)\n", " loss = net(Hamiltonian, N, D)\n",
"\n", "\n",
" # 在动态图机制下,反向传播极小化损失函数\n", " # 在动态图机制下,反向传播极小化损失函数\n",
" loss.backward()\n", " loss.backward()\n",
" opt.minimize(loss)\n", " opt.minimize(loss)\n",
" net.clear_gradients()\n", " opt.clear_grad()\n",
"\n", "\n",
" # 更新优化结果\n", " # 更新优化结果\n",
" summary_loss.append(loss.numpy())\n", " summary_loss.append(loss.numpy())\n",
" summary_iter.append(itr)\n", " summary_iter.append(itr)\n",
"\n", "\n",
" # 打印结果\n", " # 打印结果\n",
" if itr % 20 == 0:\n", " if itr % 20 == 0:\n",
" print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n", " print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n",
" print(\"iter:\", itr, \"Ground state energy:\", \n", " print(\"iter:\", itr, \"Ground state energy:\", \n",
" \"%.4f Ha\" % loss.numpy())" " \"%.4f Ha\" % loss.numpy())\n"
] ]
}, },
{ {
...@@ -382,7 +399,7 @@ ...@@ -382,7 +399,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
"\n", "\n",
"Here, we introduce how to configure the CUDA environment in Windows 10 on the x64 platform. First, check on [CUDA GPUs | NVIDIA Developer](https://developer.nvidia.com/cuda-gpus) to see if your GPU support the CUDA environment. Then, download the latest version of your graphics card driver from [NVIDIA Driver Download](https://www.nvidia.cn/Download/index.aspx?lang=cn) and install it on your computer.\n", "Here, we introduce how to configure the CUDA environment in Windows 10 on the x64 platform. First, check on [CUDA GPUs | NVIDIA Developer](https://developer.nvidia.com/cuda-gpus) to see if your GPU support the CUDA environment. Then, download the latest version of your graphics card driver from [NVIDIA Driver Download](https://www.nvidia.cn/Download/index.aspx?lang=cn) and install it on your computer.\n",
"\n", "\n",
"In [PaddlePaddle Installation Steps](https://www.paddlepaddle.org.cn/install/quick), we found that **Paddle Paddle only supports CUDA 9.0/10.0 single card mode under Windows; it does not support CUDA 9.1/9.2/10.1**, so we need to install CUDA10.0 (CUDA 9.0 is also possible in theory). Find the download link of CUDA 10.0 in [CUDA Toolkit Archive | NVIDIA Developer](https://developer.nvidia.com/cuda-toolkit-archive): [CUDA Toolkit 10.0 Archive | NVIDIA Developer](https://developer.nvidia.com/cuda-10.0-download-archive). After downloading CUDA, run the installation.\n", "In [PaddlePaddle Installation Steps](https://www.paddlepaddle.org.cn/install/quick), we found that **Paddle Paddle only supports CUDA CUDA 9.0/10.0/10.1/10.2/11.0 single card mode under Windows**, so we install CUDA10.2 here. Find the download link of CUDA 10.2 in [CUDA Toolkit Archive | NVIDIA Developer](https://developer.nvidia.com/cuda-toolkit-archive): [CUDA Toolkit 10.2 Archive | NVIDIA Developer](https://developer.nvidia.com/cuda-10.2-download-archive). After downloading CUDA, run the installation.\n",
"\n", "\n",
"During the installation process, select **Custom Installation** in the CUDA options, check all the boxes except for Visual Studio Integration (unless you are familiar with it). Then check CUDA option only. Then select the default location for the installation location (please pay attention to the installation location of your CUDA, you need to set environment variables later), and wait for the installation to complete.\n", "During the installation process, select **Custom Installation** in the CUDA options, check all the boxes except for Visual Studio Integration (unless you are familiar with it). Then check CUDA option only. Then select the default location for the installation location (please pay attention to the installation location of your CUDA, you need to set environment variables later), and wait for the installation to complete.\n",
"\n", "\n",
...@@ -42,17 +42,17 @@ ...@@ -42,17 +42,17 @@
"\n", "\n",
"### Install cuDNN\n", "### Install cuDNN\n",
"\n", "\n",
"Download cuDNN in [NVIDIA cuDNN | NVIDIA Developer](https://developer.nvidia.com/cudnn), according to [PaddlePaddle Installation Steps](https://www.paddlepaddle.org.cn/install/quick) requirements, we **need to use cuDNN 7.6+**, so we can download the latest version of cuDNN that supports CUDA 10.0. After downloading cuDNN, unzip it. Assuming the installation path of our CUDA is `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0`. After decompressing cuDNN, we take the files in `bin`, `include` and `lib` and replace the corresponding original files in the CUDA installation path (if the file already exists, replace it, if it does not exist, paste it directly into the corresponding directory). At this point, cuDNN has been installed.\n", "Download cuDNN in [NVIDIA cuDNN | NVIDIA Developer](https://developer.nvidia.com/cudnn), according to [PaddlePaddle Installation Steps](https://www.paddlepaddle.org.cn/install/quick) requirements, we **need to use cuDNN 7.6.5+**, so we can download the version 7.6.5 of cuDNN that supports CUDA 10.2. After downloading cuDNN, unzip it. Assuming the installation path of our CUDA is `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2`. After decompressing cuDNN, we take the files in `bin`, `include` and `lib` and replace the corresponding original files in the CUDA installation path (if the file already exists, replace it, if it does not exist, paste it directly into the corresponding directory). At this point, cuDNN has been installed.\n",
"\n", "\n",
"### Configure environment variables\n", "### Configure environment variables\n",
"\n", "\n",
"Next, you need to configure environment variables. Right-click \"This PC\" on the desktop of the computer (or \"This PC\" in the left column of \"File Explorer\"), select \"Properties\", and then select \"Advanced System Settings\" on the left, under the \"Advanced\" column Select \"Environmental Variables\".\n", "Next, you need to configure environment variables. Right-click \"This PC\" on the desktop of the computer (or \"This PC\" in the left column of \"File Explorer\"), select \"Properties\", and then select \"Advanced System Settings\" on the left, under the \"Advanced\" column Select \"Environmental Variables\".\n",
"\n", "\n",
"Now you enter the setting page of environment variables, select `Path` in the `System variables`, and click `Edit`. In the page that appears, check if there are two addresses `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0\\bin` and `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0\\libnvvp` (the prefix `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0` should be your CUDA installation location), if not, please add them manually.\n", "Now you enter the setting page of environment variables, select `Path` in the `System variables`, and click `Edit`. In the page that appears, check if there are two addresses `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\\bin` and `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\\libnvvp` (the prefix `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2` should be your CUDA installation location), if not, please add them manually.\n",
"\n", "\n",
"### Verify that the installation is successful\n", "### Verify that the installation is successful\n",
"\n", "\n",
"Open the command line and enter `cd C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.0\\extras\\demo_suite` to enter the CUDA installation path (this should also be your CUDA installation location). Then execute `.\\bandwidthTest.exe` and `.\\deviceQuery.exe` respectively. If both `Result = PASS` appear, the installation is successful.\n", "Open the command line and enter `cd C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\\extras\\demo_suite` to enter the CUDA installation path (this should also be your CUDA installation location). Then execute `.\\bandwidthTest.exe` and `.\\deviceQuery.exe` respectively. If both `Result = PASS` appear, the installation is successful.\n",
"\n" "\n"
] ]
}, },
...@@ -62,19 +62,13 @@ ...@@ -62,19 +62,13 @@
"source": [ "source": [
"## Install PaddlePaddle on CUDA environment\n", "## Install PaddlePaddle on CUDA environment\n",
"\n", "\n",
"According to the instructions in [PaddlePaddle Installation Steps](https://www.paddlepaddle.org.cn/install/quick), we first need to make sure our python environment is correct and use `python --version` to check the python version. Ensure that the **python version is 3.5.1+/3.6+/3.7+**, and use `python -m ensurepip` and `python -m pip --version` to check the pip version, **confirm it is 9.0.1+**. Then, use `python -m pip install paddlepaddle-gpu==1.8.4.post107 -i https://pypi.tuna.tsinghua.edu.cn/simple` to install the GPU version of PaddlePaddle.\n", "According to the instructions in [PaddlePaddle Installation Steps](https://www.paddlepaddle.org.cn/install/quick), we first need to make sure our python environment is correct and use `python --version` to check the python version. Ensure that the **python version is 3.5.1+/3.6+/3.7/3.8**, and use `python -m ensurepip` and `python -m pip --version` to check the pip version, **confirm it is 20.2.2+**. Then, use `python -m pip install paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple` to install the GPU version of PaddlePaddle.\n",
"\n" "\n",
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install Paddle Quantum\n", "## Install Paddle Quantum\n",
"\n", "\n",
"Download the Paddle Quantum installation package, modify `setup.py`, change paddlepaddle` to `paddlepaddle-gpu`, and then execute `pip install -e .` according to the installation requirements of Paddle Quantum.\n", "Download the Paddle Quantum installation package, modify `setup.py` and `requirements.txt`, change `paddlepaddle` to `paddlepaddle-gpu`, and then execute `pip install -e .` according to the installation guide of Paddle Quantum from source code.\n",
"\n", "\n",
"> If you have installed paddlepaddle-gpu and paddle_quantum in a new python environment, please also install jupyter in the new python environment, and reopen this tutorial under the new jupyter notebook and run it." "> If you have installed paddlepaddle-gpu and paddle_quantum in a new python environment, please also install jupyter in the new python environment, and reopen this tutorial under the new jupyter notebook and run it.\n"
] ]
}, },
{ {
...@@ -102,8 +96,7 @@ ...@@ -102,8 +96,7 @@
], ],
"source": [ "source": [
"import paddle \n", "import paddle \n",
"from paddle import fluid\n", "print(paddle.is_compiled_with_cuda())"
"print(fluid.is_compiled_with_cuda())"
] ]
}, },
{ {
...@@ -121,9 +114,8 @@ ...@@ -121,9 +114,8 @@
"source": [ "source": [
"```python\n", "```python\n",
"# 0 means to use GPU number 0\n", "# 0 means to use GPU number 0\n",
"place = fluid.CUDAPlace(0)\n", "paddle.set_device('gpu:0')\n",
"with fluid.dygraph.guard(place):\n", "# build and train your quantum circuit model\n",
" # build and train your quantum circuit model\n",
"```" "```"
] ]
}, },
...@@ -139,9 +131,8 @@ ...@@ -139,9 +131,8 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"```python\n", "```python\n",
"place = fluid.CPUPlace()\n", "paddle.set_device('cpu')\n",
"with fluid.dygraph.guard(place):\n", "# build and train your quantum circuit model\n",
" # build and train your quantum circuit model\n",
"```" "```"
] ]
}, },
...@@ -161,17 +152,41 @@ ...@@ -161,17 +152,41 @@
"outputs": [], "outputs": [],
"source": [ "source": [
"import os\n", "import os\n",
"import numpy\n",
"from numpy import concatenate\n", "from numpy import concatenate\n",
"from numpy import pi as PI\n", "from numpy import pi as PI\n",
"from numpy import savez, zeros\n", "from numpy import savez, zeros\n",
"from paddle import fluid\n", "from paddle import matmul, transpose\n",
"from paddle.complex import matmul, transpose\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"\n", "\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"import numpy\n", "import numpy\n",
"from paddle_quantum.VQE.chemistrysub import H2_generator\n", "\n",
"from time import time\n", "\n",
"def H2_generator():\n",
" \n",
" H = [\n",
" [-0.04207897647782277, 'i0'],\n",
" [0.17771287465139946, 'z0'],\n",
" [0.1777128746513994, 'z1'],\n",
" [-0.2427428051314046, 'z2'],\n",
" [-0.24274280513140462, 'z3'],\n",
" [0.17059738328801055, 'z0,z1'],\n",
" [0.04475014401535163, 'y0,x1,x2,y3'],\n",
" [-0.04475014401535163, 'y0,y1,x2,x3'],\n",
" [-0.04475014401535163, 'x0,x1,y2,y3'],\n",
" [0.04475014401535163, 'x0,y1,y2,x3'],\n",
" [0.12293305056183797, 'z0,z2'],\n",
" [0.1676831945771896, 'z0,z3'],\n",
" [0.1676831945771896, 'z1,z2'],\n",
" [0.12293305056183797, 'z1,z3'],\n",
" [0.1762764080431959, 'z2,z3']\n",
" ]\n",
" N = 4\n",
" \n",
" return H, N\n",
"\n",
"\n",
"\n", "\n",
"Hamiltonian, N = H2_generator()\n", "Hamiltonian, N = H2_generator()\n",
"\n", "\n",
...@@ -200,18 +215,20 @@ ...@@ -200,18 +215,20 @@
" return expectation_val\n", " return expectation_val\n",
"\n", "\n",
"\n", "\n",
"class StateNet(fluid.dygraph.Layer):\n", "class StateNet(paddle.nn.Layer):\n",
" \"\"\"\n", " \"\"\"\n",
" Construct the model net\n", " Construct the model net\n",
" \"\"\"\n", " \"\"\"\n",
"\n", "\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " def __init__(self, shape, dtype=\"float64\"):\n",
" low=0.0, high=2 * PI), dtype=\"float64\"):\n",
" super(StateNet, self).__init__()\n", " super(StateNet, self).__init__()\n",
"\n", "\n",
" # Initialize the theta parameter list and fill the initial value with the uniform distribution of [0, 2*pi]\n", " # Initialize the theta parameter list and fill the initial value with the uniform distribution of [0, 2*pi]\n",
" self.theta = self.create_parameter(\n", " self.theta = self.create_parameter(\n",
" shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " shape=shape, \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI), \n",
" dtype=dtype, \n",
" is_bias=False)\n",
"\n", "\n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self, Hamiltonian, N, D):\n", " def forward(self, Hamiltonian, N, D):\n",
...@@ -241,12 +258,12 @@ ...@@ -241,12 +258,12 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 20 loss: -0.8634\n", "iter: 20 loss: -1.0305\n",
"iter: 20 Ground state energy: -0.8634 Ha\n", "iter: 20 Ground state energy: -1.0305 Ha\n",
"iter: 40 loss: -1.1203\n", "iter: 40 loss: -1.1111\n",
"iter: 40 Ground state energy: -1.1203 Ha\n", "iter: 40 Ground state energy: -1.1111 Ha\n",
"iter: 60 loss: -1.1350\n", "iter: 60 loss: -1.1342\n",
"iter: 60 Ground state energy: -1.1350 Ha\n", "iter: 60 Ground state energy: -1.1342 Ha\n",
"iter: 80 loss: -1.1359\n", "iter: 80 loss: -1.1359\n",
"iter: 80 Ground state energy: -1.1359 Ha\n" "iter: 80 Ground state energy: -1.1359 Ha\n"
] ]
...@@ -254,40 +271,38 @@ ...@@ -254,40 +271,38 @@
], ],
"source": [ "source": [
"# 0 means to use GPU number 0\n", "# 0 means to use GPU number 0\n",
"place_gpu = fluid.CUDAPlace(0)\n", "paddle.set_device('gpu:0')\n",
"with fluid.dygraph.guard(place_gpu):\n",
" \n", " \n",
" # Determine the parameter dimension of the network\n", "# Determine the parameter dimension of the network\n",
" net = StateNet(shape=[D + 1, N, 1])\n", "net = StateNet(shape=[D + 1, N, 1])\n",
"\n", "\n",
" # Generally speaking, we use Adam optimizer to get relatively good convergence\n", "# Generally speaking, we use Adam optimizer to get relatively good convergence\n",
" # Of course, you can change to SGD or RMS prop.\n", "# Of course, you can change to SGD or RMSProp\n",
" opt = fluid.optimizer.AdamOptimizer(\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" learning_rate=LR, parameter_list=net.parameters())\n",
"\n", "\n",
" # Record optimization results\n", "# Record optimization results\n",
" summary_iter, summary_loss = [], []\n", "summary_iter, summary_loss = [], []\n",
"\n", "\n",
" # Optimization cycle\n", "# Optimization cycle\n",
" for itr in range(1, ITR + 1):\n", "for itr in range(1, ITR + 1):\n",
"\n", "\n",
" # Forward propagation to calculate loss function\n", " # Forward propagation to calculate loss function\n",
" loss = net(Hamiltonian, N, D)\n", " loss = net(Hamiltonian, N, D)\n",
"\n", "\n",
" # Under the dynamic graph mechanism, back propagation minimizes the loss function\n", " # Under the dynamic graph mechanism, back propagation minimizes the loss function\n",
" loss.backward()\n", " loss.backward()\n",
" opt.minimize(loss)\n", " opt.minimize(loss)\n",
" net.clear_gradients()\n", " opt.clear_grad()\n",
"\n", "\n",
" # Update optimization results\n", " # Update optimization results\n",
" summary_loss.append(loss.numpy())\n", " summary_loss.append(loss.numpy())\n",
" summary_iter.append(itr)\n", " summary_iter.append(itr)\n",
"\n", "\n",
" # Print results\n", " # Print results\n",
" if itr% 20 == 0:\n", " if itr% 20 == 0:\n",
" print(\"iter:\", itr, \"loss:\", \"%.4f\"% loss.numpy())\n", " print(\"iter:\", itr, \"loss:\", \"%.4f\"% loss.numpy())\n",
" print(\"iter:\", itr, \"Ground state energy:\",\n", " print(\"iter:\", itr, \"Ground state energy:\",\n",
" \"%.4f Ha\"% loss.numpy())" " \"%.4f Ha\"% loss.numpy())"
] ]
}, },
{ {
...@@ -306,53 +321,51 @@ ...@@ -306,53 +321,51 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 20 loss: -0.7789\n", "iter: 20 loss: -1.0639\n",
"iter: 20 Ground state energy: -0.7789 Ha\n", "iter: 20 Ground state energy: -1.0639 Ha\n",
"iter: 40 loss: -1.0741\n", "iter: 40 loss: -1.1209\n",
"iter: 40 Ground state energy: -1.0741 Ha\n", "iter: 40 Ground state energy: -1.1209 Ha\n",
"iter: 60 loss: -1.1271\n", "iter: 60 loss: -1.1345\n",
"iter: 60 Ground state energy: -1.1271 Ha\n", "iter: 60 Ground state energy: -1.1345 Ha\n",
"iter: 80 loss: -1.1351\n", "iter: 80 loss: -1.1360\n",
"iter: 80 Ground state energy: -1.1351 Ha\n" "iter: 80 Ground state energy: -1.1360 Ha\n"
] ]
} }
], ],
"source": [ "source": [
"# Use CPU\n", "# Use CPU\n",
"place_cpu = fluid.CPUPlace()\n", "paddle.set_device(\"cpu\")\n",
"with fluid.dygraph.guard(place_cpu):\n", "\n",
" \n", "# Determine the parameter dimension of the network\n",
" # Determine the parameter dimension of the network\n", "net = StateNet(shape=[D + 1, N, 1])\n",
" net = StateNet(shape=[D + 1, N, 1])\n",
"\n", "\n",
" # Generally speaking, we use Adam optimizer to get relatively good convergence\n", "# Generally speaking, we use Adam optimizer to get relatively good convergence\n",
" # Of course you can change to SGD or RMS prop.\n", "# Of course you can change to SGD or RMSProp\n",
" opt = fluid.optimizer.AdamOptimizer(\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" learning_rate=LR, parameter_list=net.parameters())\n",
"\n", "\n",
" # Record optimization results\n", "# Record optimization results\n",
" summary_iter, summary_loss = [], []\n", "summary_iter, summary_loss = [], []\n",
"\n", "\n",
" # Optimization cycle\n", "# Optimization cycle\n",
" for itr in range(1, ITR + 1):\n", "for itr in range(1, ITR + 1):\n",
"\n", "\n",
" # Forward propagation to calculate loss function\n", " # Forward propagation to calculate loss function\n",
" loss = net(Hamiltonian, N, D)\n", " loss = net(Hamiltonian, N, D)\n",
"\n", "\n",
" # Under the dynamic graph mechanism, back propagation minimizes the loss function\n", " # Under the dynamic graph mechanism, back propagation minimizes the loss function\n",
" loss.backward()\n", " loss.backward()\n",
" opt.minimize(loss)\n", " opt.minimize(loss)\n",
" net.clear_gradients()\n", " opt.clear_grad()\n",
"\n", "\n",
" # Update optimization results\n", " # Update optimization results\n",
" summary_loss.append(loss.numpy())\n", " summary_loss.append(loss.numpy())\n",
" summary_iter.append(itr)\n", " summary_iter.append(itr)\n",
"\n", "\n",
" # Print results\n", " # Print results\n",
" if itr% 20 == 0:\n", " if itr% 20 == 0:\n",
" print(\"iter:\", itr, \"loss:\", \"%.4f\"% loss.numpy())\n", " print(\"iter:\", itr, \"loss:\", \"%.4f\"% loss.numpy())\n",
" print(\"iter:\", itr, \"Ground state energy:\",\n", " print(\"iter:\", itr, \"Ground state energy:\",\n",
" \"%.4f Ha\"% loss.numpy())" " \"%.4f Ha\"% loss.numpy())"
] ]
}, },
{ {
...@@ -392,7 +405,7 @@ ...@@ -392,7 +405,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"这是一份简洁、实用的关于量子机器学习(Quantum Machine Learnig,QML)的介绍,面向读者包括但不限于物理、数学和计算机背景。本手册主要采用 Jupyter Notebook 的交互形式 (调用 Numpy, Matplotlib等 Python包以及飞桨Paddlepaddle深度学习框架来实现基于线性代数的量子运算和机器学习优化问题)。我们不仅提供了关于量子计算的一些基础教程同时还能手把手带你完成属于你自己的第一份量子机器学习算法。这并不是一份关于量子计算的百科全书,但我们涉及的案例经常出现在教科书中以及文献中。如果你想深入挖掘一些相关的基础知识,我们也提供了一些外部链接方便用户自己学习。\n", "这是一份简洁、实用的关于量子机器学习(Quantum Machine Learnig,QML)的介绍,面向读者包括但不限于物理、数学和计算机背景。本手册主要采用 Jupyter Notebook 的交互形式 (调用 Numpy, Matplotlib 等 Python 包以及飞桨 Paddlepaddle 深度学习框架来实现基于线性代数的量子运算和机器学习优化问题)。我们不仅提供了关于量子计算的一些基础教程同时还能手把手带你完成属于你自己的第一份量子机器学习算法。这并不是一份关于量子计算的百科全书,但我们涉及的案例经常出现在教科书中以及文献中。如果你想深入挖掘一些相关的基础知识,我们也提供了一些外部链接方便用户自己学习。\n",
"\n", "\n",
"量子计算是由量子力学与计算理论交叉形成的新型学科,本质上是通过量子力学的基本规律去操控信息单元量子比特(quantum bit, qubit)的新型计算模式。与经典计算模型相比,在许多特定的信息处理任务上量子计算被普遍认为具有更强大的信息处理优势。关于量子计算的介绍与入门知识可以参考 [1-2],想要系统性地学习量子计算学科的读者请参阅 Nielsen & Chuang 编写的经典教材 [3]。近期,量子计算领域中一个热门的课题是如何有效地结合量子计算和人工智能两者的潜能。量子机器学习便是这样一门结合了量子计算与机器学习的交叉学科,一方面研究者们希望利用量子计算的信息处理优势去促进人工智能的发展,另一方面也存在可能性去利用现有的人工智能的技术突破量子计算的研发瓶颈。关于量子机器学习的入门资料可以参考 [4-6]。\n", "量子计算是由量子力学与计算理论交叉形成的新型学科,本质上是通过量子力学的基本规律去操控信息单元量子比特(quantum bit, qubit)的新型计算模式。与经典计算模型相比,在许多特定的信息处理任务上量子计算被普遍认为具有更强大的信息处理优势。关于量子计算的介绍与入门知识可以参考 [1-2],想要系统性地学习量子计算学科的读者请参阅 Nielsen & Chuang 编写的经典教材 [3]。近期,量子计算领域中一个热门的课题是如何有效地结合量子计算和人工智能两者的潜能。量子机器学习便是这样一门结合了量子计算与机器学习的交叉学科,一方面研究者们希望利用量子计算的信息处理优势去促进人工智能的发展,另一方面也存在可能性去利用现有的人工智能的技术突破量子计算的研发瓶颈。关于量子机器学习的入门资料可以参考 [4-6]。\n",
"\n", "\n",
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
"- 具体的量子机器学习案例—— 变分量子特征求解器(VQE)\n", "- 具体的量子机器学习案例—— 变分量子特征求解器(VQE)\n",
"\n", "\n",
"\n", "\n",
"最后修改于: 2021年1月9日 由量桨 Paddle Quantum 开发小组共同完成。\n", "最后修改于: 2021年3月2日 由量桨 Paddle Quantum 开发小组共同完成。\n",
"\n", "\n",
"<hr>" "<hr>"
] ]
...@@ -90,14 +90,13 @@ ...@@ -90,14 +90,13 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"我们推荐使用 [Anaconda](https://www.anaconda.com/download) 作为 Python3的开发环境,支持多种主流操作系统(Windows, MacOS, 以及 Linux)。Anaconda本身提供 Scipy, Numpy, Matplotlib等科学计算、作图包,最主要的是其自带 Python开发环境的管理器 conda,可以用来安装或者更新主流 Python包。这里我们提供一个例子来学习使用 conda创建和管理环境:\n", "我们推荐使用 [Anaconda](https://www.anaconda.com/download) 作为 Python3 的开发环境,支持多种主流操作系统(Windows, MacOS, 以及 Linux)。Anaconda 本身提供 Scipy, Numpy, Matplotlib 等科学计算、作图包,最主要的是其自带 Python 开发环境的管理器 conda,可以用来安装或者更新主流 Python 包。这里我们提供一个例子来学习使用 conda 创建和管理环境:\n",
"\n", "\n",
"1. 首先进入命令行 (Terminal) 界面:Windows用户可以通过 `Anaconda Prompt`/ Mac用户可以使用组合键 `command⌘ + 空格` 再输入 `Terminal`。\n", "1. 首先进入命令行 (Terminal) 界面:Windows 用户可以通过 `Anaconda Prompt`/ Mac用户可以使用组合键 `command⌘ + 空格` 再输入 `Terminal`。\n",
"1. 进入 Terminal 后输入 `conda create --name paddle_quantum_env python=3.6` 创建名为 `paddle_quantum_env` 的 Python3.6 环境。\n", "1. 进入 Terminal 后输入 `conda create --name paddle_quantum_env python=3.7` 创建名为 `paddle_quantum_env` 的 Python3.7 环境。\n",
"1. 在 Terminal 内通过 `conda env list` 查看已有的环境,然后通过 `conda activate paddle_quantum_env ` 进入我们刚建立的环境。\n", "1. 在 Terminal 内通过 `conda env list` 查看已有的环境,然后通过 `conda activate paddle_quantum_env ` 进入我们刚建立的环境。\n",
"1. 为了能正确运行 Jupyter Notebook 我们还需要安装 `conda install jupyter notebook` 或者 `pip install jupyter notebook`。安装完成之后,如果你想开启 Jupyter 只需要在Terminal内激活正确的环境然后输入 `jupyter notebook` 即可。\n", "1. 为了能正确运行 Jupyter Notebook 我们还需要安装 `conda install jupyter notebook` 或者 `pip install jupyter notebook`。安装完成之后,如果你想开启 Jupyter 只需要在Terminal内激活正确的环境然后输入 `jupyter notebook` 即可。\n",
"\n", "\n",
"<img src=\"figures/intro-fig-terminal.png\" width=\"650\" >\n",
"\n", "\n",
"关于 conda 更多的本地指令请参考 [官方教程](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html)。\n", "关于 conda 更多的本地指令请参考 [官方教程](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html)。\n",
"<span class=\"blue\"> 此外,你也可以通过使用 <a href=\"https://docs.anaconda.com/anaconda/navigator/\"> Anaconda Navigator</a> 开启 jupyter notebook。\n", "<span class=\"blue\"> 此外,你也可以通过使用 <a href=\"https://docs.anaconda.com/anaconda/navigator/\"> Anaconda Navigator</a> 开启 jupyter notebook。\n",
...@@ -105,8 +104,8 @@ ...@@ -105,8 +104,8 @@
"以下是这个教程中你需要使用的包:\n", "以下是这个教程中你需要使用的包:\n",
"<ul>\n", "<ul>\n",
" <li>Numpy\n", " <li>Numpy\n",
" <li>Paddlepaddle 1.8.5\n", " <li>Paddlepaddle 2.0.1+\n",
" <li>Paddle Quantum \n", " <li>Paddle Quantum 2.0.0+\n",
"</ul>" "</ul>"
] ]
}, },
...@@ -129,15 +128,15 @@ ...@@ -129,15 +128,15 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:47:03.252187Z", "end_time": "2021-03-09T03:52:49.041480Z",
"start_time": "2021-01-09T12:46:59.940104Z" "start_time": "2021-03-09T03:52:43.796510Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"from paddle import fluid\n", "import paddle\n",
"from paddle.complex import matmul, transpose, trace\n", "from paddle import matmul, transpose, trace\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import dagger, random_pauli_str_generator, pauli_str_to_matrix\n", "from paddle_quantum.utils import dagger, random_pauli_str_generator, pauli_str_to_matrix\n",
"from paddle_quantum.state import vec, vec_random, density_op, density_op_random" "from paddle_quantum.state import vec, vec_random, density_op, density_op_random"
...@@ -472,8 +471,8 @@ ...@@ -472,8 +471,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:47:08.582194Z", "end_time": "2021-03-09T03:53:01.312586Z",
"start_time": "2021-01-09T12:47:08.337302Z" "start_time": "2021-03-09T03:53:01.145669Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -490,27 +489,24 @@ ...@@ -490,27 +489,24 @@
"source": [ "source": [
"# 设置角度参数 theta = pi\n", "# 设置角度参数 theta = pi\n",
"theta = np.array([np.pi])\n", "theta = np.array([np.pi])\n",
"\n",
"# 启动 Paddle 动态图模式\n",
"with fluid.dygraph.guard():\n",
" \n",
" # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable\n",
" theta = fluid.dygraph.to_variable(theta)\n",
" \n",
" # 设置计算所需的量子比特数量\n",
" num_qubits = 1\n",
" \n",
" # 初始化我们的单比特量子电路\n",
" cir = UAnsatz(num_qubits)\n",
" \n", " \n",
" # 在第一个量子比特(第0号量子比特)的位置上施加一个 Rx 旋转门, 角度为 pi\n", "# 我们需要将 Numpy array 转换成 Paddle 中的 Tensor\n",
" which_qubit = 0\n", "theta = paddle.to_tensor(theta)\n",
" cir.rx(theta, which_qubit)\n", "\n",
" \n", "# 设置计算所需的量子比特数量\n",
" # 打印出这个量子门\n", "num_qubits = 1\n",
" # 转换成 numpy \n", "\n",
" print('量子门的矩阵表达式为:')\n", "# 初始化我们的单比特量子电路\n",
" print(cir.U.numpy())" "cir = UAnsatz(num_qubits)\n",
"\n",
"# 在第一个量子比特(第0号量子比特)的位置上施加一个 Rx 旋转门, 角度为 pi\n",
"which_qubit = 0\n",
"cir.rx(theta, which_qubit)\n",
"\n",
"# 打印出这个量子门\n",
"# 转换成 numpy \n",
"print('量子门的矩阵表达式为:')\n",
"print(cir.U.numpy())"
] ]
}, },
{ {
...@@ -539,18 +535,17 @@ ...@@ -539,18 +535,17 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"theta = \"your code\"\n", "theta = \"your code\"\n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" theta = fluid.dygraph.to_variable(theta)\n", "theta = paddle.to_tensor(theta)\n",
" num_qubits = 1\n", "num_qubits = 1\n",
" cir = UAnsatz(\"your code\")\n", "cir = UAnsatz(\"your code\")\n",
" cir.ry(\"your code\")\n", "cir.ry(\"your code\")\n",
" print(cir.U.numpy())" "print(cir.U.numpy())"
] ]
}, },
{ {
...@@ -607,11 +602,11 @@ ...@@ -607,11 +602,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:47:11.924347Z", "end_time": "2021-03-09T03:53:07.533977Z",
"start_time": "2021-01-09T12:47:11.900263Z" "start_time": "2021-03-09T03:53:07.497242Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -630,30 +625,27 @@ ...@@ -630,30 +625,27 @@
"source": [ "source": [
"# 设置角度参数 theta \n", "# 设置角度参数 theta \n",
"theta = np.full([4], np.pi)\n", "theta = np.full([4], np.pi)\n",
"\n",
"# 启动 Paddle 动态图模式\n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable\n", "# 我们需要将 Numpy array 转换成 Paddle 中的 Tensor\n",
" theta = fluid.dygraph.to_variable(theta)\n", "theta = paddle.to_tensor(theta)\n",
" \n", "\n",
" # 初始化量子电路\n", "# 初始化量子电路\n",
" num_qubits = 2\n", "num_qubits = 2\n",
" cir = UAnsatz(num_qubits)\n", "cir = UAnsatz(num_qubits)\n",
" \n",
" # 添加单比特旋转门\n",
" cir.ry(theta[0], 0)\n",
" cir.ry(theta[1], 1)\n",
"\n", "\n",
" # 添加两比特门\n", "# 添加单比特旋转门\n",
" cir.cnot([0, 1])\n", "cir.ry(theta[0], 0)\n",
"cir.ry(theta[1], 1)\n",
"\n", "\n",
" # 添加单比特旋转门\n", "# 添加两比特门\n",
" cir.ry(theta[2], 0)\n", "cir.cnot([0, 1])\n",
" cir.ry(theta[3], 1)\n", "\n",
" \n", "# 添加单比特旋转门\n",
" print('图中量子神经网络 U(theta=pi) 的矩阵表达式是:')\n", "cir.ry(theta[2], 0)\n",
" print(cir.U.numpy().real)" "cir.ry(theta[3], 1)\n",
"\n",
"print('图中量子神经网络 U(theta=pi) 的矩阵表达式是:')\n",
"print(cir.U.numpy().real)"
] ]
}, },
{ {
...@@ -683,28 +675,31 @@ ...@@ -683,28 +675,31 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 6,
"metadata": {}, "metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:09.041159Z",
"start_time": "2021-03-09T03:53:09.026637Z"
}
},
"outputs": [], "outputs": [],
"source": [ "source": [
"theta = np.full([6], np.pi)\n", "theta = np.full([6], np.pi)\n",
"with fluid.dygraph.guard():\n",
" \n",
" theta = fluid.dygraph.to_variable(theta)\n",
" \n",
" num_qubits = 3\n",
" cir = UAnsatz(num_qubits) \n",
" \n",
" cir.ry(theta[0], 0)\n",
" cir.ry(theta[1], 1)\n",
" cir.ry(theta[2], 2)\n",
" \n", " \n",
" cir.cnot([0, 1])\n", "theta = paddle.to_tensor(theta)\n",
" cir.cnot([1, 2])\n",
"\n", "\n",
" cir.ry(theta[3], 0)\n", "num_qubits = 3\n",
" cir.ry(theta[4], 1)\n", "cir = UAnsatz(num_qubits) \n",
" cir.ry(theta[5], 2)\n", "\n",
" " "cir.ry(theta[0], 0)\n",
"cir.ry(theta[1], 1)\n",
"cir.ry(theta[2], 2)\n",
"\n",
"cir.cnot([0, 1])\n",
"cir.cnot([1, 2])\n",
"\n",
"cir.ry(theta[3], 0)\n",
"cir.ry(theta[4], 1)\n",
"cir.ry(theta[5], 2)"
] ]
}, },
{ {
...@@ -737,17 +732,17 @@ ...@@ -737,17 +732,17 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:47:17.393379Z", "end_time": "2021-03-09T03:53:12.042782Z",
"start_time": "2021-01-09T12:47:16.964739Z" "start_time": "2021-03-09T03:53:11.531307Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -760,37 +755,34 @@ ...@@ -760,37 +755,34 @@
], ],
"source": [ "source": [
"N = 3 # 设置量子比特数\n", "N = 3 # 设置量子比特数\n",
"\n",
"# 启动 Paddle 动态图模式\n",
"with fluid.dygraph.guard():\n",
" \n",
" # 初始化量子电路\n",
" cir = UAnsatz(N)\n",
" \n",
" # 给每一个量子比特施加哈达玛门 H\n",
" cir.superposition_layer()\n",
" \n", " \n",
" # 制备输出态\n", "# 初始化量子电路\n",
" # 如果用户不输入初始量子态,默认初始为|00..0>\n", "cir = UAnsatz(N)\n",
" final_state = cir.run_state_vector()\n", "\n",
" \n", "# 给每一个量子比特施加哈达玛门 H\n",
" # 获取概率分布的理论值,令 shots = 0\n", "cir.superposition_layer()\n",
" cir.measure(shots = 0, plot = True)" "\n",
"# 制备输出态\n",
"# 如果用户不输入初始量子态,默认初始为|00..0>\n",
"final_state = cir.run_state_vector()\n",
"\n",
"# 获取概率分布的理论值,令 shots = 0\n",
"res = cir.measure(shots = 0, plot = True)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:47:21.610944Z", "end_time": "2021-03-09T03:53:12.698149Z",
"start_time": "2021-01-09T12:47:21.228136Z" "start_time": "2021-03-09T03:53:12.187946Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEPCAYAAABP1MOPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAXIklEQVR4nO3dfbRddX3n8feHIGqF1gcitSQYqkGLT6gRXXWmRQsWlhawooZaFUfFjjKVZbUNU0VLnSlqdaxjbI31gbajEa3VtETR8aGd2kETEMUEIxGChNYaeVBbRzHynT/ODpycnHvvySX77Jvs92utu3L2/u1zzyf3j/u5e//2Q6oKSVJ/HdR1AElStywCSeo5i0CSes4ikKSeswgkqecO7jrA3jr88MNr2bJlXceQpP3K5Zdf/p2qWjxubL8rgmXLlrFx48auY0jSfiXJ9TONeWhIknrOIpCknrMIJKnnLAJJ6jmLQJJ6ziKQpJ6zCCSp5ywCSeo5i0CSem6/u7L4rli26pJOP3/bhU/t9PMlaRz3CCSp5ywCSeo5i0CSeq7VIkhycpItSbYmWTXDNs9KsjnJpiTvbzOPJGlPrU0WJ1kErAZOArYDG5Ksq6rNQ9ssB84DnlhVtyS5f1t5JEnjtblHcDywtaqurarbgLXAaSPbvBhYXVW3AFTVt1vMI0kao80iOBK4YWh5e7Nu2DHAMUk+n+SyJCeP+0ZJzk6yMcnGHTt2tBRXkvqp68nig4HlwAnAmcC7ktx7dKOqWlNVK6pqxeLFY5+0JkmapzaL4EZg6dDykmbdsO3Auqr6cVVdB3ydQTFIkqakzSLYACxPcnSSQ4CVwLqRbT7KYG+AJIczOFR0bYuZJEkjWiuCqtoJnANcClwNXFxVm5JckOTUZrNLgZuSbAY+C7yqqm5qK5MkaU+t3muoqtYD60fWnT/0uoBXNF+SpA50PVksSeqYRSBJPWcRSFLPWQSS1HMWgST1nEUgST1nEUhSz1kEktRzFoEk9ZxFIEk9ZxFIUs9ZBJLUcxaBJPWcRSBJPWcRSFLPWQSS1HMWgST1nEUgST1nEUhSz1kEktRzFoEk9ZxFIEk9ZxFIUs9ZBJLUc60WQZKTk2xJsjXJqjHjZyXZkeTK5utFbeaRJO3p4La+cZJFwGrgJGA7sCHJuqraPLLpB6vqnLZySJJm1+YewfHA1qq6tqpuA9YCp7X4eZKkeWizCI4Ebhha3t6sG/WMJF9J8uEkS8d9oyRnJ9mYZOOOHTvayCpJvdX1ZPHfAsuq6pHAp4CLxm1UVWuqakVVrVi8ePFUA0rSga7NIrgRGP4Lf0mz7g5VdVNV/ahZ/HPgsS3mkSSN0WYRbACWJzk6ySHASmDd8AZJHjC0eCpwdYt5JEljtHbWUFXtTHIOcCmwCHhPVW1KcgGwsarWAb+d5FRgJ3AzcFZbeSRJ47VWBABVtR5YP7Lu/KHX5wHntZlBkjS7rieLJUkdswgkqecsAknqOYtAknrOIpCknrMIJKnnLAJJ6jmLQJJ6ziKQpJ6zCCSp5ywCSeo5i0CSes4ikKSeswgkqecsAknqOYtAknrOIpCknrMIJKnnLAJJ6jmLQJJ6ziKQpJ6zCCSp5ywCSeo5i0CSem6iIkjyxCT3al7/ZpK3JHngBO87OcmWJFuTrJplu2ckqSQrJo8uSdoXJt0j+FPgB0keBfwO8A3gL2Z7Q5JFwGrgFOBY4Mwkx47Z7jDg5cAX9iK3JGkfmbQIdlZVAacBb6+q1cBhc7zneGBrVV1bVbcBa5v3j/pD4A3ADyfMIknahyYtgu8nOQ94LnBJkoOAu83xniOBG4aWtzfr7pDkMcDSqrpktm+U5OwkG5Ns3LFjx4SRJUmTmLQIng38CPhPVfUtYAnwprvywU2ZvIXBoaZZVdWaqlpRVSsWL158Vz5WkjRioiJofvn/NXD3ZtV3gL+Z4203AkuHlpc063Y5DHg48Lkk24AnAOucMJak6Zr0rKEXAx8G3tmsOhL46Bxv2wAsT3J0kkOAlcC6XYNV9d2qOryqllXVMuAy4NSq2rh3/wVJ0l0x6aGhlwFPBL4HUFXXAPef7Q1VtRM4B7gUuBq4uKo2JbkgyanzjyxJ2pcOnnC7H1XVbUkASHIwUHO9qarWA+tH1p0/w7YnTJhFkrQPTbpH8PdJ/itwzyQnAR8C/ra9WJKkaZm0CFYBO4CrgJcw+Cv/1W2FkiRNz0SHhqrqduBdzZck6QAyaxEkubiqnpXkKsbMCVTVI1tLJkmairn2CF7e/Pu0toNIkrox6xxBVf1L8/KlVXX98Bfw0vbjSZLaNulk8Ulj1p2yL4NIkrox1xzBf2bwl//PJ/nK0NBhwOfbDCZJmo655gjeD3wc+CMGp5Du8v2qurm1VJKkqZmrCKqqtiV52ehAkvtaBpK0/5tkj+BpwOUMTh/N0FgBP99SLknSlMxaBFX1tObfo6cTR5I0bXNNFj9mtvGqumLfxpEkTdtch4bePMtYAU/eh1kkSR2Y69DQk6YVRJLUjbkODT25qj6T5NfHjVfVR9qJJUmalrkODf0y8Bng18aMFWARSNJ+bq5DQ69t/n3BdOJIkqZt0ofX3y/J25JckeTyJH+S5H5th5MktW/Sm86tZfCEsmcAZzSvP9hWKEnS9Ez68PoHVNUfDi2/Psmz2wgkSZquSfcIPplkZZKDmq9nAZe2GUySNB1znT76fe68x9C5wF81QwcB/wa8ss1wkqT2zXXW0GHTCiJJ6sakcwQkuQ+wHLjHrnVV9Q9thJIkTc+kp4++CPgHBvMCf9D8+7oJ3ndyki1JtiZZNWb8t5JcleTKJP+Y5Ni9iy9JuqsmnSx+OfA44Prm/kOPBm6d7Q1JFgGrGTzb+FjgzDG/6N9fVY+oquOANwJvmTy6JGlfmLQIflhVPwRIcveq+hrwkDneczywtaqurarbGFyLcNrwBlX1vaHFezGYmJYkTdGkcwTbk9wb+CjwqSS3ANfP8Z4jgRuGvwfw+NGNmsdgvgI4hBlua53kbOBsgKOOOmrCyJKkSUy0R1BVT6+qW6vqdcBrgHcDp++LAFW1uqoeBPwe8OoZtllTVSuqasXixYv3xcdKkhp7c9bQY4D/wODwzeebwz2zuRFYOrS8pFk3k7XAn06aR5K0b0x61tD5wEXA/YDDgfcmGfvX+5ANwPIkRyc5BFgJrBv5vsuHFp8KXDNpcEnSvjHpHsFzgEcNTRhfCFwJvH6mN1TVziTnMDjVdBHwnqralOQCYGNVrQPOSXIi8GPgFuD58/6fSJLmZdIi+GcGF5L9sFm+O7Mf5gGgqtYD60fWnT/0+uUTfr4kqSVz3WvofzKYE/gusCnJp5rlk4Avth9PktS2ufYINjb/Xg78zdD6z7WSRpI0dXPddO6iXa+bCd9jmsUtVfXjNoNJkqZjojmCJCcwOGtoG4NbUi9N8nxvOidJ+79JJ4vfDDylqrYAJDkG+ADw2LaCSZKmY9J7Dd1tVwkAVNXXgbu1E0mSNE2T7hFcnuTPufMJZc/hzolkSdJ+bNIi+C3gZcBvN8v/B3hHK4kkSVM1ZxE0zxX4clU9FJ8XIEkHnDnnCKrqJ8CWJN7/WZIOQJMeGroPgyuLvwj8+66VVXVqK6kkSVMzaRG8ptUUkqTOzHWvoXswmCh+MHAV8O6q2jmNYJKk6ZhrjuAiYAWDEjiFwYVlkqQDyFyHho6tqkcAJHk33nFUkg44c+0R3HFjOQ8JSdKBaa49gkcl+V7zOsA9m+UAVVU/3Wo6SVLr5roN9aJpBZEkdWPSm85Jkg5QFoEk9ZxFIEk9ZxFIUs9ZBJLUcxaBJPVcq0WQ5OQkW5JsTbJqzPgrkmxO8pUkn07ywDbzSJL21FoRNA+0Wc3gHkXHAmcmOXZksy8BK6rqkcCHgTe2lUeSNF6bewTHA1ur6tqqug1YC5w2vEFVfbaqftAsXgYsaTGPJGmMNovgSOCGoeXtzbqZvBD4+LiBJGcn2Zhk444dO/ZhREnSgpgsTvKbDG53/aZx41W1pqpWVNWKxYsXTzecJB3gJn1C2XzcCCwdWl7SrNtNkhOB3wd+uap+1GIeSdIYbe4RbACWJzk6ySHASmDd8AZJHg28Ezi1qr7dYhZJ0gxaK4Lm+QXnAJcCVwMXV9WmJBck2fXQ+zcBhwIfSnJlknUzfDtJUkvaPDREVa0H1o+sO3/o9Yltfr4kaW4LYrJYktQdi0CSes4ikKSeswgkqecsAknqOYtAknrOIpCknrMIJKnnLAJJ6jmLQJJ6ziKQpJ6zCCSp5ywCSeo5i0CSes4ikKSeswgkqecsAknqOYtAknrOIpCknrMIJKnnLAJJ6jmLQJJ6ziKQpJ6zCCSp51otgiQnJ9mSZGuSVWPGfynJFUl2JjmjzSySpPEObusbJ1kErAZOArYDG5Ksq6rNQ5t9EzgLeGVbOfYXy1Zd0unnb7vwqTOOLeRsC5k/N+0vWisC4Hhga1VdC5BkLXAacEcRVNW2Zuz2FnNIkmbR5qGhI4Ebhpa3N+v2WpKzk2xMsnHHjh37JJwkaWC/mCyuqjVVtaKqVixevLjrOJJ0QGmzCG4Elg4tL2nWSZIWkDaLYAOwPMnRSQ4BVgLrWvw8SdI8tFYEVbUTOAe4FLgauLiqNiW5IMmpAEkel2Q78EzgnUk2tZVHkjRem2cNUVXrgfUj684fer2BwSEjSVJH9ovJYklSeywCSeo5i0CSes4ikKSeswgkqecsAknqOYtAknrOIpCknrMIJKnnLAJJ6jmLQJJ6ziKQpJ6zCCSp5ywCSeo5i0CSes4ikKSeswgkqecsAknqOYtAknrOIpCknrMIJKnnLAJJ6rmDuw4g3RXLVl3S6edvu/CpnX7+fC3kn9tCznagco9AknrOIpCknmu1CJKcnGRLkq1JVo0Zv3uSDzbjX0iyrM08kqQ9tVYESRYBq4FTgGOBM5McO7LZC4FbqurBwP8A3tBWHknSeG1OFh8PbK2qawGSrAVOAzYPbXMa8Lrm9YeBtydJVVWLuSRpXg7Uiey09Ts3yRnAyVX1omb5ucDjq+qcoW2+2myzvVn+RrPNd0a+19nA2c3iQ4AtrYSe2+HAd+bcqhtmmx+zzY/Z5qfLbA+sqsXjBvaL00erag2wpuscSTZW1Yquc4xjtvkx2/yYbX4WarY2J4tvBJYOLS9p1o3dJsnBwM8AN7WYSZI0os0i2AAsT3J0kkOAlcC6kW3WAc9vXp8BfMb5AUmartYODVXVziTnAJcCi4D3VNWmJBcAG6tqHfBu4C+TbAVuZlAWC1nnh6dmYbb5Mdv8mG1+FmS21iaLJUn7B68slqSeswgkqecsAknqOYtgAknum+S+XeeQpDZYBDNIclSStUl2AF8Avpjk2826ZR3HW/CSHJHkMc3XEV3nmUuSQ7vOIHXFs4ZmkOT/Am8FPlxVP2nWLQKeCZxbVU/oMN6MklxVVY/o8POPA/6MwcWBuy4gXALcCry0qq7oJtnsknyzqo5aADmOAI5sFm+sqn/tMs9ckhxaVf/WcYYwuLfZHT834IsL+ZqkJA+tqq91nWMXi2AGSa6pquV7OzYNSX59piHgz2a6n8g0JLkSeElVfWFk/ROAd1bVozoJNsjwipmGgN+vqs4O/1mg8/78pwDvAK5h95/bgxn83D7ZVbbZdP1zG7Vf3GuoI5cneQdwEXBDs24pgyuhv9RZqoEPAv8LGNfi95hyllH3Gi0BgKq6LMm9ugg05L8DbwJ2jhnr+jDp+5i5QN8LLNQC7fqQ2p8AJ1bVtuGVSY4G1gO/0EWoJsPbZhoC7j3FKHOyCGb2PAbPS/gDdt/l3HVFdJe+AvxxVX11dCDJiR3kGfbxJJcAf8HuBfo84BOdpRq4AvhoVV0+OpDkRR3kGWaBzs/BwPYx628E7jblLKNeAPwO8KMxY2dOOcusPDS0H0ryH4Hrq+qbY8ZWVNXGDmINZziFwbMmdivQqlrfXSpI8hDgptHbnDdjR3R5PL756/FBjC/Q64Zv395Btn8C/ssMBXpDVS0d87apSHIe8CxgLbv/3FYCF1fVH3WY7TPAq6vqn8aMXVdVR3cQayyLYAbN3VBfCJzO7r/QPga8u6p+3FE0HaAWeIHeXFU7xox1WqBNhl9g/M9t88zval9zyvkPq+oHXeaYhEUwgyQfYDBRdxF37nouYTBHcN+qenZH0YZL6unAzzWrF3xJJVlTVWfPveX0LeRsUtssghkk+XpVHbO3Y9OwwEtqpjNvAny5qpZMM89uARZ2tp8BzmPwl+0RDE4E+DaDcr+wqm5dANlOB+6/kLLNJsnHq+qUrnOMs9CyOVk8s5uTPBP466q6HSDJQQyuI7il02Tw2DFFtB24LMnXuwg0ZAdwPYNfrrtUs3z/ThLdaSFnuxj4DPCkqvoWQJKfBc5qxp7SXbQ7sp0wku35XWdL8piZhoDjphhlzwALONso9whm0Fw9/AbgSQz++obBKV+fBVZV1XWdBAOSXAa8mfEl9YqqenyH2a4BfmWGieyuJxYXcrYtVfWQvR2bhgWe7SfA37N7ue/yhKq655Qj3WEhZxvlHsEMqmpbktcxuGZgt8niLkugsZJBSa1Ocmuz7t4MSqrrh/u8FbgPsMcvW+CN042yh7eycLNdn+R3gYt2Tb42VxmfxZ1nw3RlIWe7msH1F9eMDiQx24TcI5hBkt9j8Et1LbtfsbgSWFtVF3aVDWY8U+JjVXV1d6kGkjyU8WdxmG0GSe4DrGKQbddhqn9lcN3KhVXV2eHIBZ7tDOCqqtoyZuz0qvro9FPd8fkLNtsoi2AGzbH2h42egdM8f3lTx7eYWLAl1fzl+BtNtuGJbLPNU5IXVNV7u84xjtnmZ6FlswhmkORrwK9W1fUj6x8IfLLj46ILuaTMto8ttPvSDDPb/Cy0bM4RzOxc4NPNBOOu43lHMbiZVWdXeTZuZ3D9wPUj6x/QjHXJbPOQ5CszDTE4nbQzZpufhZxtlEUwg6r6RJJj2PP2tht23Za6Q+eycEvqXMw2H0cAv8qepyYH2OMWBVNmtvlZyNl2YxHMojk187Kuc4xayCVltnn7O+DQqrpydCDJ56aeZndmm5+FnG03zhFIUs91fQtZSVLHLAJJ6jmLQAe0JEuSfCzJNUmuTfL2JHef4H1jn8Ob5IJdD/9Jcm6Sn5phu6cl+VKSLyfZnOQlzfrTkxw7wedPtJ20L1gEOmAlCfARBk8lWw4sB+7JXbidRFWdX1X/u1k8F9ijCJLcDVgD/FrzjOZHA59rhk8HJvkFP+l20l3mZLEOWEl+BXhtVf3S0LqfZnAdwVLgDGDFrqd/Jfk7Bo8A/VyzR/AuBnfW/Bawsqp2JHkfg7NBfg74Y2AL8J2qetLQZ9wX+BrwwKr6f0Prf7F573ebr2cATwbOBg4BtgLPZXBnytHtAFYDi4EfAC+uqq/tkx+Ues89Ah3IHgbs9njFqvoesI3BtQOzuRewsaoexuAOkq8d+T5vA/6ZwW2jnzQydjOD+/Bcn+QDSZ6T5KDmkYXrgFdV1XFV9Q3gI1X1uGbP4WrghTNst4bB4yIfC7wSeMde/zSkGXgdgTTe7cAHm9d/xeAQ08Sq6kVJHgGcyOAX90kM7tY56uFJXs/g7rGHApeObpDkUOAXgQ8NjnYBMOc8hzQpi0AHss0MDv/coTk09LMMDuk8nN33iu8xy/fa62OoVXUVcFWSvwSuY3wRvA84vaq+nOQs4IQx2xwE3FpVx+1tBmkSHhrSgezTwE8leR5AkkUMHujz9ubY/TbguCQHJVnK4IrjXQ7izhL5DeAfx3z/7wOHja5McmiSE4ZWHced9zcafc9hwL80E8zPGfe9m8NZ1zVPzCMDj5rtPy7tDYtAB6wanAnxdOCM5v5CNwG3V9V/azb5PIO/1DcDbwOuGHr7vwPHJ/kqgwndC8Z8xBrgE0k+O7I+wO8m2ZLkSuAPuHNvYC3wqubU0gcBrwG+0GQZnvwd3e45wAuTfBnYxODZANI+4VlD6o3mrJ0PAE+vqivm2l7qC4tAknrOQ0OS1HMWgST1nEUgST1nEUhSz1kEktRzFoEk9dz/B9VMzjhMqx3WAAAAAElFTkSuQmCC\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -803,22 +795,19 @@ ...@@ -803,22 +795,19 @@
], ],
"source": [ "source": [
"N = 3 # 设置量子比特数\n", "N = 3 # 设置量子比特数\n",
"\n",
"# 启动 Paddle 动态图模式\n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" # 初始化量子电路\n", "# 初始化量子电路\n",
" cir = UAnsatz(N)\n", "cir = UAnsatz(N)\n",
" \n", "\n",
" # 给每一个量子比特施加 Ry(pi/4)旋转\n", "# 给每一个量子比特施加 Ry(pi/4)旋转\n",
" cir.weak_superposition_layer()\n", "cir.weak_superposition_layer()\n",
" \n", "\n",
" # 制备输出态\n", "# 制备输出态\n",
" # 如果用户不输入初始量子态,默认初始为|00..0>\n", "# 如果用户不输入初始量子态,默认初始为|00..0>\n",
" final_state = cir.run_state_vector()\n", "final_state = cir.run_state_vector()\n",
" \n", "\n",
" # 获取概率分布的理论值,令 shots = 0\n", "# 获取概率分布的理论值,令 shots = 0\n",
" cir.measure(shots = 0, plot = True)" "res = cir.measure(shots = 0, plot = True)"
] ]
}, },
{ {
...@@ -864,18 +853,18 @@ ...@@ -864,18 +853,18 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 9,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:47:40.125099Z", "end_time": "2021-03-09T03:53:14.040033Z",
"start_time": "2021-01-09T12:47:39.631740Z" "start_time": "2021-03-09T03:53:13.566616Z"
}, },
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAY4AAAEPCAYAAABV6CMBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAgq0lEQVR4nO3de5ydVX3v8c83ASIVUC7R0iSQVGIpiEYJkdML9QaGF0piBQlEAYtiD9LKy9YajhZqpKdQW7UcgxLL1QsB8UJOCaJHxHOqghkwEhJMGSBAItbhJigFDHzPH88a2NnZM/PsYfbsHfJ9v177Nc9e61lr//b8Mb951lrPemSbiIiIuiZ0O4CIiNi6JHFERERbkjgiIqItSRwREdGWJI6IiGjLdt0OYDzssccenj59erfDiIjYqtx00033257cXL5NJI7p06fT19fX7TAiIrYqku5uVZ6hqoiIaEsSR0REtKWjiUPSXEnrJPVLWtSi/oOS1kq6RdJ3JO3dUHeCpNvL64SG8gMlrS59nitJnfwOERGxuY4lDkkTgSXA4cB+wLGS9ms67cfAbNuvBK4E/rG03Q04E3gtMAc4U9Kupc1ngfcCM8trbqe+Q0REbKmTVxxzgH7bd9p+ElgGzGs8wfZ3bT9W3t4ATC3Hbwa+bftB2w8B3wbmStoT2MX2Da422boUmN/B7xAREU06mTimAPc2vN9QyoZyEnDNCG2nlOMR+5R0sqQ+SX0DAwNthh4REUPpiclxSe8EZgOfGKs+bS+1Pdv27MmTt1iGHBERo9TJxLERmNbwfmop24ykNwEfAY60/cQIbTfy7HDWkH1GRETndDJxrARmSpohaQdgAbC88QRJrwbOp0oav2iouhY4TNKuZVL8MOBa2/cBj0g6uKymOh64qoPfISIimnTsznHbmySdSpUEJgIX2l4jaTHQZ3s51dDUTsBXyqrae2wfaftBSR+nSj4Ai20/WI5PAS4GdqSaE7mGbdT0RVd37bPXn31E1z47Irqro1uO2F4BrGgqO6Ph+E3DtL0QuLBFeR/wijEMMyIi2tATk+MREbH1SOKIiIi2JHFERERbkjgiIqItSRwREdGWJI6IiGhLEkdERLQliSMiItqSxBEREW1J4oiIiLYkcURERFuSOCIioi1JHBER0ZYkjoiIaEtHt1WPbVeeFRLx/JUrjoiIaEsSR0REtKWjiUPSXEnrJPVLWtSi/hBJN0vaJOmohvLXS1rV8Hpc0vxSd7GkuxrqZnXyO0RExOY6NschaSKwBDgU2ACslLTc9tqG0+4BTgT+urGt7e8Cs0o/uwH9wLcaTvmQ7Ss7FXtERAytk5Pjc4B+23cCSFoGzAOeSRy215e6p4fp5yjgGtuPdS7UiIioq5NDVVOAexvebyhl7VoAXNZU9veSbpH0KUmTRhtgRES0r6cnxyXtCRwAXNtQfDqwL3AQsBvw4SHaniypT1LfwMBAx2ONiNhWdDJxbASmNbyfWsra8Q7g67Z/M1hg+z5XngAuohoS24LtpbZn2549efLkNj82IiKG0sk5jpXATEkzqBLGAuC4Nvs4luoK4xmS9rR9nyQB84FbxyDWIeVGtoiIzXXsisP2JuBUqmGm24ArbK+RtFjSkQCSDpK0ATgaOF/SmsH2kqZTXbF8r6nrL0laDawG9gDO6tR3iIiILXV0yxHbK4AVTWVnNByvpBrCatV2PS0m022/YWyjjIiIdvT05HhERPSeJI6IiGhLEkdERLQliSMiItqSxBEREW1J4oiIiLYkcURERFuSOCIioi1JHBER0ZYkjoiIaEsSR0REtCWJIyIi2pLEERERbUniiIiItiRxREREW0ZMHJL+UNILy/E7JX1S0t6dDy0iInpRnSuOzwKPSXoV8FfAHcClHY0qIiJ6Vp3Escm2gXnAZ2wvAXbubFgREdGr6iSORyWdDrwLuFrSBGD7Op1LmitpnaR+SYta1B8i6WZJmyQd1VT3lKRV5bW8oXyGpBtLn5dL2qFOLBERMTbqJI5jgCeAP7P9c6pnhH9ipEaSJgJLgMOB/YBjJe3XdNo9wInAl1t08V+2Z5XXkQ3l5wCfsr0P8BBwUo3vEBERY2TExFGSxVeBSaXofuDrNfqeA/TbvtP2k8AyquGuxr7X274FeLpOsJIEvAG4shRdAsyv0zYiIsZGnVVV76X6Q31+KZoCfKNG31OAexvebyhldb1AUp+kGyTNL2W7Aw/b3jRSn5JOLu37BgYG2vjYiIgYTp2hqvcDfwg8AmD7duAlnQyq2Nv2bOA44NOSXtZOY9tLbc+2PXvy5MmdiTAiYhtUJ3E8UYaaAJC0HeAa7TYC0xreTy1ltdjeWH7eCVwPvBp4AHhxiaHtPiMi4rmrkzi+J+l/ADtKOhT4CvC/a7RbCcwsq6B2ABYAy0doA4CkXSVNKsd7UF3xrC3Lgr8LDK7AOgG4qk6fERExNuokjkXAALAaeB+wAvjoSI3KPMSpwLXAbcAVttdIWizpSABJB0naABwNnC9pTWn++0CfpJ9QJYqzba8tdR8GPiipn2rO44J6XzUiIsbCdiOdYPtp4PPl1RbbK6gSTWPZGQ3HK6mGm5rb/QA4YIg+76RasRUREV0wZOKQdIXtd0haTYs5Dduv7GhkERHRk4a74vhA+fmW8QgkIiK2DkPOcdi+rxyeYvvuxhdwyviEFxERvabO5PihLcoOH+tAIiJi6zDcHMd/p7qy+F1JtzRU7Qx8v9OBRUQ8H0xfdHXXPnv92Ud0pN/h5ji+DFwD/APVktxBj9p+sCPRREREzxsucdj2eknvb66QtFuSR0TEtmmkK463ADdRLcdVQ52B3+1gXBER0aOGTBy231J+zhi/cCIiotcNNzn+muEa2r557MOJiIheN9xQ1T8PU2eqBypFRMQ2ZrihqtePZyAREbF1GG6o6g22r5P0p63qbX+tc2FFRESvGm6o6k+A64C3tqgzkMQREbENGm6o6szy893jF05ERPS6EfeqkrS7pHMl3SzpJkn/Imn38QguIiJ6T51NDpdRPQHw7VSPbB0ALu9kUBER0bvqJI49bX/c9l3ldRbw0jqdS5oraZ2kfkmLWtQfUq5kNkk6qqF8lqQfSloj6RZJxzTUXSzpLkmrymtWnVgiImJs1Ekc35K0QNKE8noH1XPEhyVpIrCEagv2/YBjJe3XdNo9wIlU25s0egw43vb+wFzg05Je3FD/IduzymtVje8QERFjZLjluI/y7B5VpwFfLFUTgF8Bfz1C33OA/vKMcCQtA+YBawdPsL2+1D3d2ND2fzQc/0zSL4DJwMMjf6WIiOik4Z4AuLPtXcrPCba3K68Jtnep0fcU4N6G9xtKWVskzQF2AO5oKP77MoT1KUmThmh3sqQ+SX0DAwPtfmxERAyhzlAVknaVNKfMSRwi6ZBOB1Y+d0/gC8C7bQ9elZwO7AscBOwGfLhVW9tLbc+2PXvy5MnjEW5ExDZhuBsAAZD0HuADwFRgFXAw8ENG3qtqIzCt4f3UUlaLpF2Aq4GP2L5hsLzhWehPSLqIkYfMIiJiDNW54vgA1X/3d5f9q15NvbmGlcBMSTMk7QAsAJbXCaqc/3XgUttXNtXtWX4KmA/cWqfPiIgYG3USx+O2HweQNMn2T4HfG6mR7U3AqVQrsG4DrrC9RtJiSUeW/g6StAE4Gjhf0prS/B3AIcCJLZbdfknSamA1sAdwVt0vGxERz92IQ1XAhrIU9hvAtyU9BNxdp3PbK4AVTWVnNByvpBrCam73RZ5dxdVcl+3cIyK6aMTEYftt5fDvJH0XeBHwzY5GFRERPavOFcfg0wD/iOq+ju/bfrKjUUVERM+qs8nhGcAlwO5UcwoXSfpopwOLiIjeVOeKYyHwqoYJ8rOpluVmUjq2StMXXd21z15/9hFd++yIsVJnVdXPgBc0vJ9EG/djRETE88twe1X9L6o5jV8CayR9u7w/FPjR+IQXERG9Zrihqr7y8yaqm/EGXd+xaCIioucN9+jYSwaPy53cLy9v19n+TacDi4iI3lRnr6rXUa2qWk+1xfo0SSfY/r8djSwiInpSnVVV/wwcZnsdgKSXA5cBB3YysIiI6E11VlVtP5g04JmHLG3fuZAiIqKX1bniuEnSv/Ls3lELeXbiPCIitjF1EsefA+8H/rK8/3/AeR2LKCIietqwiUPSROAntvcFPjk+IUVERC8bdo7D9lPAOkl7jVM8ERHR4+oMVe1Kdef4j4BfDxbaPrJjUUVERM+qkzj+tuNRRETEVmPIoSpJL5B0GtVjXfeleg7H9wZfdTqXNFfSOkn9kha1qD9E0s2SNkk6qqnuBEm3l9cJDeUHSlpd+jy3PHs8IiLGyXBzHJcAs6me7X041Y2AtZWJ9SWl7X7AsZL2azrtHuBE4MtNbXcDzgReC8wBzpS0a6n+LPBeYGZ5zW0nroiIeG6GG6raz/YBAJIuoP0dcecA/bbvLH0sA+YBawdPsL2+1D3d1PbNwLdtP1jqvw3MlXQ9sIvtG0r5pcB84Jo2Y4uIiFEa7orjmY0MbW8aRd9TgHsb3m8oZc+l7ZRyPGKfkk6W1Cepb2BgoHbQERExvOESx6skPVJejwKvHDyW9Mh4BThatpfanm179uTJk7sdTkTE88Zw26pPfI59bwSmNbyfSv0nB24EXtfU9vpSPnWUfUZExBios8nhaK0EZkqaUZ7nsQBYXrPttcBhknYtk+KHAdfavg94RNLBZTXV8cBVnQg+IiJa61jiKPMip1IlgduAK2yvkbRY0pEAkg6StIFqye/5ktaUtg8CH6dKPiuBxYMT5cApwL8C/cAdZGI8ImJc1bkBcNRsrwBWNJWd0XC8ks2HnhrPuxC4sEV5H/CKsY00IiLq6uRQVUREPA8NecVRVlJ5qHrbu3QkooiI6GnDraraGUDSx4H7gC9QPXN8IbDnuEQXERE9p85Q1ZG2z7P9qO1HbH+W6g7wiIjYBtVJHL+WtFDSREkTJC2kYXv1iIjYttRJHMcB7wD+s7yOLmUREbENGnE5btmIMENTEeNg+qKru/bZ688+omufHVuXEa84JL1c0nck3Vrev1LSRzsfWkRE9KI6Q1WfB06n7JZr+xaq7UMiImIbVCdx/Jbt5mdxjGab9YiIeB6okzjul/Qyys2A5RGv93U0qoiI6Fl19qp6P7AU2FfSRuAuqpsAIyJiGzRs4ijPDT/F9pskvRCYYPvR8QktIiJ60bCJw/ZTkv6oHOemv4iIqDVU9WNJy4Gv0HDHuO2vdSyqiIjoWXUSxwuAB4A3NJQZSOKIiNgG1blz/N3jEUhERGwdRkwcki6ixXM5bP9ZRyKKiIieVuc+jn8Dri6v7wC7AL+q07mkuZLWSeqXtKhF/SRJl5f6GyVNL+ULJa1qeD0taVapu770OVj3knpfNSIixkKdoaqvNr6XdBnw7yO1K0t5lwCHAhuAlZKW217bcNpJwEO295G0ADgHOMb2l4AvlX4OAL5he1VDu4Xl2eMRETHORvPM8ZlAnf/y5wD9tu+0/SSwjC132Z0HXFKOrwTeKElN5xxb2kZERA+oM8fR/OzxnwMfrtH3FODehvcbgNcOdY7tTZJ+CewO3N9wzjFsmXAukvQU8FXgLNtbzMFIOhk4GWCvvfaqEW5ERNRRZ6hq5/EIpBVJrwUes31rQ/FC2xsl7UyVON4FXNrc1vZSqq1SmD179haJJSIiRqfO8zj+sGw3gqR3SvqkpL1r9L0RmNbwfmopa3mOpO2AF1HdMzJoAXBZYwPbG8vPR4EvUw2JRUTEOKkzx/FZ4DFJrwL+CriDFv/ht7ASmClphqQdqJLA8qZzlgMnlOOjgOsGh50kTaB6ZO0z8xuStpO0RzneHngLcCsRETFu6iSOTeWP+TzgM7aXACMOX9neBJwKXAvcBlxhe42kxZKOLKddAOwuqR/4INC4ZPcQ4F7bdzaUTQKulXQLsIrqiuXzNb5DRESMkTpbjjwq6XTgncAh5Upg+zqd214BrGgqO6Ph+HHg6CHaXg8c3FT2a+DAOp8dERGdUSdxHAMcB5xk++eS9gI+0dmwIiLqm77o6q599vqzj+jaZ3dLnVVVPwc+2fD+HurNcURExPNQnVVVB0taKelXkp6U9FS53yIiIrZBdSbHP0N19/btwI7Ae4DzOhlURET0rlpbjtjuBybafsr2RcDczoYVERG9qs7k+GPlPoxVkv4RuI/R7XEVERHPA3USwLvKeadSPTp2GvD2TgYVERG9q86qqrsl7Qjsaftj4xBTRET0sDqrqt5KdZf2N8v7WZKatw6JiIhtRJ2hqr+j2kjwYYDyQKUZHYsoIiJ6Wp3E8RvbzfdtZJvyiIhtVJ1VVWskHQdMlDQT+EvgB50NKyIielWdK46/APYHnqB6NsYjwGkdjCkiInpYnVVVjwEfKa+IiNjGDZk4Rlo5ZfvI4eojIuL5abgrjv8G3Es1PHUjoHGJKCIietpwieO3gUOpNjg8DrgauMz2mvEILCIietOQk+NlQ8Nv2j6B6kl8/cD1kk6t27mkuZLWSeqXtKhF/SRJl5f6GyVNL+XTJf2XpFXl9bmGNgdKWl3anCspV0IREeNo2MlxSZOAI6iuOqYD5wJfr9OxpInAEqqrlg3ASknLba9tOO0k4CHb+0haAJxD9cRBgDtsz2rR9WeB91INn62g2qn3mjoxRUTEczfkFYekS4EfAq8BPmb7INsft72xZt9zgH7bd9p+ElgGzGs6Zx5wSTm+EnjjcFcQkvYEdrF9g21TPYlwfs14IiJiDAx3H8c7gZnAB4AfSHqkvB6V9EiNvqdQTa4P2lDKWp5jexPwS2D3UjdD0o8lfU/SHzecv2GEPgGQdLKkPkl9AwMDNcKNiIg6hhyqst3NZ27cB+xl+wFJBwLfkLR/Ox3YXgosBZg9e3a2SImIGCOdTA4bqZ7dMWhqKWt5jqTtgBcBD9h+wvYDALZvAu4AXl7OnzpCnxER0UGdTBwrgZmSZpQnCC4Amm8qXA6cUI6PAq6zbUmTy+Q6kn6XasjsTtv3AY9IOrjMhRwPXNXB7xAREU3qbHI4KrY3laW71wITgQttr5G0GOizvRy4APiCpH7gQarkAnAIsFjSb4CngT+3/WCpOwW4GNiRajVVVlRFRIyjjiUOANsrqJbMNpad0XD8OHB0i3ZfBb46RJ99wCvGNtKIiKirmxPgERGxFUriiIiItiRxREREW5I4IiKiLUkcERHRliSOiIhoSxJHRES0JYkjIiLaksQRERFtSeKIiIi2dHTLkYh4/pi+6Oquffb6s4/o2mfHlnLFERERbUniiIiItiRxREREW5I4IiKiLUkcERHRliSOiIhoS0cTh6S5ktZJ6pe0qEX9JEmXl/obJU0v5YdKuknS6vLzDQ1tri99riqvl3TyO0RExOY6dh+HpInAEuBQYAOwUtJy22sbTjsJeMj2PpIWAOcAxwD3A2+1/TNJr6B6bvmUhnYLyyNkIyJinHXyimMO0G/7TttPAsuAeU3nzAMuKcdXAm+UJNs/tv2zUr4G2FHSpA7GGhERNXUycUwB7m14v4HNrxo2O8f2JuCXwO5N57wduNn2Ew1lF5Vhqr+VpFYfLulkSX2S+gYGBp7L94iIiAY9PTkuaX+q4av3NRQvtH0A8Mfl9a5WbW0vtT3b9uzJkyd3PtiIiG1EJxPHRmBaw/uppazlOZK2A14EPFDeTwW+Dhxv+47BBrY3lp+PAl+mGhKLiIhx0snEsRKYKWmGpB2ABcDypnOWAyeU46OA62xb0ouBq4FFtr8/eLKk7STtUY63B94C3NrB7xAREU06ljjKnMWpVCuibgOusL1G0mJJR5bTLgB2l9QPfBAYXLJ7KrAPcEbTsttJwLWSbgFWUV2xfL5T3yEiIrbU0W3Vba8AVjSVndFw/DhwdIt2ZwFnDdHtgWMZY0REtKenJ8cjIqL3JHFERERbkjgiIqItSRwREdGWJI6IiGhLEkdERLQliSMiItqSxBEREW1J4oiIiLYkcURERFuSOCIioi1JHBER0ZYkjoiIaEsSR0REtCWJIyIi2pLEERERbUniiIiItiRxREREWzqaOCTNlbROUr+kRS3qJ0m6vNTfKGl6Q93ppXydpDfX7TMiIjqrY4lD0kRgCXA4sB9wrKT9mk47CXjI9j7Ap4BzStv9gAXA/sBc4DxJE2v2GRERHdTJK445QL/tO20/CSwD5jWdMw+4pBxfCbxRkkr5MttP2L4L6C/91ekzIiI6aLsO9j0FuLfh/QbgtUOdY3uTpF8Cu5fyG5raTinHI/UJgKSTgZPL219JWjeK7zAW9gDuH01DnTPGkWwpsY1OYhudxDY63Yxt71aFnUwcXWV7KbC023FI6rM9u9txtJLYRiexjU5iG51ejK2TQ1UbgWkN76eWspbnSNoOeBHwwDBt6/QZEREd1MnEsRKYKWmGpB2oJruXN52zHDihHB8FXGfbpXxBWXU1A5gJ/KhmnxER0UEdG6oqcxanAtcCE4ELba+RtBjos70cuAD4gqR+4EGqREA57wpgLbAJeL/tpwBa9dmp7zBGuj5cNozENjqJbXQS2+j0XGyq/sGPiIioJ3eOR0REW5I4IiKiLUkcERHRliSODpC0m6Tduh1HREQnJHGMEUl7SVomaQC4EfiRpF+UsuldDq/nSXqppNeU10u7Hc9IJO3U7RgiuiWrqsaIpB8CnwaubFg6PBE4GjjN9sFdDG9IklbbPqCLnz8L+BzVzZ+DN3NOBR4GTrF9c3ciG56ke2zv1e04oEq6PLslz0bb/9nNeEYiaSfbv+pyDKLa++6Z3xvwI/fwH0RJ+9r+abfjgCSOMSPpdtsz260bD5L+dKgq4HO2J49nPJsFIK0C3mf7xqbyg4Hzbb+qK4FVMXxwqCrgI7a7OhyZpDvqzz8MOA+4nc1/b/tQ/d6+1a3YhtPt31uj5+1eVV1wk6TzqHb7HdyIcRrVnfE/7lpUlcuBLwGt/kt4wTjH0uyFzUkDwPYNkl7YjYAa/E/gE1Q3oTbrhWHeixk66V4E9GrS7fYw378Ab7K9vrGw7FKxAvj9bgRVYjh3qCrgxeMYyrCSOMbO8VTPF/kYm1/+Dt4h3023AP9k+9bmCklv6kI8ja6RdDVwKZsn3OOBb3YtqsrNwDds39RcIek9XYinWZLu6GxHtbN2s43A9uMcS7N3A38FPNGi7thxjmVIGaraBkj6Y+Bu2/e0qJttu68LYTXGcDjVc1U2S7i2V3QvKpD0e8ADtrfY0lrSS7s9l1D+O30ZrZPuXbZP7WJsPwD+Yoike6/taS2ajQtJpwPvoHqeT+PvbQFwhe1/6GJs1wEftf2DFnV32Z7RhbC2kMQxRsruvicB89n8D+BVwAW2f9Ol0OJ5rMeT7oO2B1rU9ULS/X1a/97Wdi+qaik/8Ljtx7oZx0iSOMaIpMuoJiUv4dnL4KlUcxy72T6mS6E1JrW3Ab9Tins+qUlaavvkkc8cf70cW0SnJXGMEUn/Yfvl7daNhx5PakOtTBLwE9tTxzOezQLo4dgAJL0IOJ3qP+eXUi1++AXVPwRn2364B2KbD7ykl2IbjqRrbB/e7Tha6aXYMjk+dh6UdDTwVdtPA0iaQHUfx0NdjQwObJG4NgA3SPqPbgTUYAC4m+qP8SCX9y/pSkTP6uXYAK4ArgNeb/vnAJJ+Gzix1B3WvdCeie11TbGd0O3YJL1mqCpg1jiGsmUAPRxbo1xxjJFyd/g5wOup/ruHavncd4FFtu/qSmCApBuAf6Z1Uvug7ZbPbR+n2G4H3jjExH23J1F7NrYSwzrbv9du3Xjo8dieAr7H5v8QDDrY9o7jHNIzejm2RrniGCO210v6O6p7NjabHO9m0igWUCW1JZIeLmUvpkpqC7oU06BPA7sCW/xxBv5xfEPZwqfp3dgA7pb0N8Alg5PN5S7yE3l2tVC39HJst1Hd/3J7c4WkxFZDrjjGiKQPU/0RXsbmd6MuAJbZPrtbscGQq0iusn1b96KqSNqX1itcEtswJO0KLKKKb3Do7D+p7h0623bXhkh7PLajgNW217Wom2/7G+Mf1TOf37OxNUriGCNlrmD/5hVK5dnoa7q85UjPJrXyX+lxJbbGifvE9hxIerfti7odRyuJbXR6KbYkjjEi6afAm23f3VS+N/CtLo/p9nJSS2wd0Ev7GjVLbKPTS7FljmPsnAZ8p0yoDo5F7kW1cVrX7uAtnqa6f+PupvI9S103JbZRknTLUFVUy3O7JrGNTi/H1iiJY4zY/qakl7PlVs0rB7dZ76LT6N2kdhqJbbReCryZLZd7C9hiy4pxlthGp5dje0YSxxgqS11v6HYczXo5qSW25+TfgJ1sr2qukHT9uEezucQ2Or0c2zMyxxEREW3p9vbGERGxlUniiIiItiRxRDSRNFXSVZJul3SnpM9ImlSjXcvnaEtaPPjALEmnSfqtIc57i6QfS/qJpLWS3lfK50var8bn1zov4rlK4ohoIEnA16ie/DcTmAnsyHPYYsT2Gbb/T3l7GrBF4pC0PbAUeGt5zvqrgetL9XygTkKoe17Ec5LJ8YgGkt4InGn7kIayXaju5ZgGHAXMHny6nqR/o3os7/XliuPzVDu//hxYYHtA0sVUq2V+B/gnYB1wv+3XN3zGbsBPgb1t/1dD+R+Utr8sr7cDbwBOBnYA+oF3Ue2c2nwewBJgMvAY8F7bPx2TX1Rs03LFEbG5/YHNHndq+xFgPdX9G8N5IdBne3+qHU7PbOrnXOBnVNugv76p7kGqfZzulnSZpIWSJpRHiC4HPmR7lu07gK/ZPqhcmdwGnDTEeUupHt96IPDXwHlt/zYiWsh9HBFj52ng8nL8Raohr9psv0fSAcCbqP7QH0q1m2yzV0g6i2qH452Aa5tPkLQT8AfAV6rRNwBGnKeJqCOJI2Jza6mGo55Rhqp+m2qI6RVsfqX+gmH6ansc2PZqYLWkLwB30TpxXAzMt/0TSScCr2txzgTgYduz2o0hYiQZqorY3HeA35J0PICkiVQPwfpMmXtYD8ySNEHSNKq7ygdN4Nmkcxzw7y36fxTYublQ0k6SXtdQNItn98hqbrMzcF+ZUF/Yqu8yvHZXeSolqrxquC8eUVcSR0QDV6tF3gYcVfaoegB42vbfl1O+T3UlsBY4F7i5ofmvgTmSbqWawF7c4iOWAt+U9N2mcgF/I2mdpFXAx3j2amMZ8KGyVPdlwN8CN5ZYGie7m89bCJwk6SfAGqpnY0Q8Z1lVFTGMsqrpMuBttm8e6fyIbUESR0REtCVDVRER0ZYkjoiIaEsSR0REtCWJIyIi2pLEERERbUniiIiItvx/cLSMSvkFLhUAAAAASUVORK5CYII=\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -890,25 +879,22 @@ ...@@ -890,25 +879,22 @@
"N = 4 # 设置量子比特数\n", "N = 4 # 设置量子比特数\n",
"DEPTH = 6 # 设置量子电路深度\n", "DEPTH = 6 # 设置量子电路深度\n",
"theta = np.random.randn(DEPTH, N, 3)\n", "theta = np.random.randn(DEPTH, N, 3)\n",
"\n",
"# 启动 Paddle 动态图模式\n",
"with fluid.dygraph.guard():\n",
" \n",
" # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable\n",
" theta = fluid.dygraph.to_variable(theta)\n",
" \n", " \n",
" # 初始化量子电路\n", "# 我们需要将 Numpy array 转换成 Paddle 中的 Tensor\n",
" cir = UAnsatz(N)\n", "theta = paddle.to_tensor(theta)\n",
" \n", "\n",
" # 添加深度为 D = 6 的复数强纠缠结构QNN {Rz+Ry+Rz/U3 + CNOT's}\n", "# 初始化量子电路\n",
" cir.complex_entangled_layer(theta, DEPTH)\n", "cir = UAnsatz(N)\n",
" \n", "\n",
" # 制备输出态\n", "# 添加深度为 D = 6 的复数强纠缠结构QNN {Rz+Ry+Rz/U3 + CNOT's}\n",
" # 如果用户不输入初始量子态,默认初始为|00..0>\n", "cir.complex_entangled_layer(theta, DEPTH)\n",
" final_state = cir.run_state_vector()\n", "\n",
" \n", "# 制备输出态\n",
" # 测量输出态的[0,1,2]号量子比特2048次,统计测量结果的频率\n", "# 如果用户不输入初始量子态,默认初始为|00..0>\n",
" cir.measure(shots = 2048, which_qubits = [0, 1, 2], plot = True)" "final_state = cir.run_state_vector()\n",
"\n",
"# 测量输出态的[0,1,2]号量子比特2048次,统计测量结果的频率\n",
"res = cir.measure(shots = 2048, which_qubits = [0, 1, 2], plot = True)"
] ]
}, },
{ {
...@@ -942,11 +928,11 @@ ...@@ -942,11 +928,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 10,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:41.024881Z", "end_time": "2021-03-09T03:53:27.327236Z",
"start_time": "2021-01-09T12:47:50.905119Z" "start_time": "2021-03-09T03:53:15.824502Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -954,8 +940,8 @@ ...@@ -954,8 +940,8 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"[[-0.00172454+0.j -0.00029211+0.j 0.00071415+0.j ... 0.00040607+0.j\n", "[[ 0.00034024+0.j -0.00015082+0.j 0.00038722+0.j ... -0.00041021+0.j\n",
" -0.00104915+0.j 0.00085908+0.j]]\n" " -0.00070034+0.j -0.00021523+0.j]]\n"
] ]
} }
], ],
...@@ -970,24 +956,21 @@ ...@@ -970,24 +956,21 @@
"initial_state1 = vec(N)\n", "initial_state1 = vec(N)\n",
"# 调用内置的随机量子态 |psi>\n", "# 调用内置的随机量子态 |psi>\n",
"initial_state2 = vec_random(N)\n", "initial_state2 = vec_random(N)\n",
"\n",
"# 启动 Paddle 动态图模式\n",
"with fluid.dygraph.guard():\n",
" \n",
" # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable\n",
" theta = fluid.dygraph.to_variable(theta)\n",
" initial_state = fluid.dygraph.to_variable(initial_state1)\n",
" \n",
" # 初始化量子电路\n",
" cir = UAnsatz(N)\n",
" \n",
" # 添加深度为 Depth 的实数强纠缠结构QNN {Ry+CNOT's}\n",
" cir.real_entangled_layer(theta, DEPTH)\n",
" \n", " \n",
" # 制备输出态\n", "# 我们需要将 Numpy array 转换成 Paddle 中的 Tensor\n",
" # 如果用户不输入初始量子态,默认初始为|00..0>\n", "theta = paddle.to_tensor(theta)\n",
" final_state = cir.run_state_vector(initial_state)\n", "initial_state = paddle.to_tensor(initial_state1)\n",
" print(final_state.numpy())" "\n",
"# 初始化量子电路\n",
"cir = UAnsatz(N)\n",
"\n",
"# 添加深度为 Depth 的实数强纠缠结构QNN {Ry+CNOT's}\n",
"cir.real_entangled_layer(theta, DEPTH)\n",
"\n",
"# 制备输出态\n",
"# 如果用户不输入初始量子态,默认初始为|00..0>\n",
"final_state = cir.run_state_vector(initial_state)\n",
"print(final_state.numpy())"
] ]
}, },
{ {
...@@ -1005,11 +988,11 @@ ...@@ -1005,11 +988,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 11,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:41.307338Z", "end_time": "2021-03-09T03:53:27.433188Z",
"start_time": "2021-01-09T12:48:41.028222Z" "start_time": "2021-03-09T03:53:27.333861Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -1017,10 +1000,10 @@ ...@@ -1017,10 +1000,10 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"[[ 0.20642449+0.j -0.24205478+0.j -0.27795534+0.j 0.1672236 +0.j]\n", "[[ 0.04269908+0.j 0.01452372+0.j 0.15539789+0.j -0.12851626+0.j]\n",
" [-0.24205478+0.j 0.2838351 +0.j 0.32593235+0.j -0.19608755+0.j]\n", " [ 0.01452372+0.j 0.00494012+0.j 0.05285723+0.j -0.04371368+0.j]\n",
" [-0.27795534+0.j 0.32593235+0.j 0.37427328+0.j -0.22517044+0.j]\n", " [ 0.15539789+0.j 0.05285723+0.j 0.56555089+0.j -0.4677186 +0.j]\n",
" [ 0.1672236 +0.j -0.19608755+0.j -0.22517044+0.j 0.13546713+0.j]]\n" " [-0.12851626+0.j -0.04371368+0.j -0.4677186 +0.j 0.38680991+0.j]]\n"
] ]
} }
], ],
...@@ -1037,24 +1020,21 @@ ...@@ -1037,24 +1020,21 @@
"initial_state2 = density_op_random(N, real_or_complex=2, rank=4)\n", "initial_state2 = density_op_random(N, real_or_complex=2, rank=4)\n",
"# 调用内置的计算基下的完全混合态 \n", "# 调用内置的计算基下的完全混合态 \n",
"initial_state3 = completely_mixed_computational(N)\n", "initial_state3 = completely_mixed_computational(N)\n",
"\n",
"# 启动 Paddle 动态图模式\n",
"with fluid.dygraph.guard():\n",
" \n",
" # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable\n",
" theta = fluid.dygraph.to_variable(theta)\n",
" initial_state = fluid.dygraph.to_variable(initial_state1)\n",
" \n",
" # 初始化量子电路\n",
" cir = UAnsatz(N)\n",
" \n",
" # 添加深度为 Depth 的实数强纠缠结构QNN {Ry+CNOT's}\n",
" cir.real_entangled_layer(theta, DEPTH)\n",
" \n", " \n",
" # 制备输出态\n", "# 我们需要将 Numpy array 转换成 Paddle 中的 Tensor\n",
" # 如果用户不输入初始量子态,默认初始为|00..0><00..0|\n", "theta = paddle.to_tensor(theta)\n",
" final_state = cir.run_density_matrix(initial_state)\n", "initial_state = paddle.to_tensor(initial_state1)\n",
" print(final_state.numpy())" "\n",
"# 初始化量子电路\n",
"cir = UAnsatz(N)\n",
"\n",
"# 添加深度为 Depth 的实数强纠缠结构QNN {Ry+CNOT's}\n",
"cir.real_entangled_layer(theta, DEPTH)\n",
"\n",
"# 制备输出态\n",
"# 如果用户不输入初始量子态,默认初始为|00..0><00..0|\n",
"final_state = cir.run_density_matrix(initial_state)\n",
"print(final_state.numpy())"
] ]
}, },
{ {
...@@ -1095,17 +1075,17 @@ ...@@ -1095,17 +1075,17 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 12,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:42.231220Z", "end_time": "2021-03-09T03:53:27.924758Z",
"start_time": "2021-01-09T12:48:41.331283Z" "start_time": "2021-03-09T03:53:27.452981Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -1120,32 +1100,28 @@ ...@@ -1120,32 +1100,28 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"我们制备出的贝尔态是:\n", "我们制备出的贝尔态是:\n",
"[0. +0.j 0.70710678+0.j 0.70710678+0.j 0. +0.j]\n" "[0.70710678+0.j 0. +0.j 0. +0.j 0.70710678+0.j]\n"
] ]
} }
], ],
"source": [ "source": [
"# 启动 Paddle 动态图模式\n", "# 初始化量子电路\n",
"with fluid.dygraph.guard():\n", "cir = UAnsatz(2)\n",
" \n",
" # 初始化量子电路\n",
" cir = UAnsatz(2)\n",
"\n", "\n",
" # 添加量子门\n", "# 添加量子门\n",
" cir.x(1)\n", "cir.h(0)\n",
" cir.h(0)\n", "cir.cnot([0, 1]) \n",
" cir.cnot([0, 1]) \n", "\n",
" \n", "# 制备输出态\n",
" # 制备输出态\n", "# 如果用户不输入初始量子态,默认初始为|00..0>\n",
" # 如果用户不输入初始量子态,默认初始为|00..0>\n", "output_state = cir.run_state_vector()\n",
" output_state = cir.run_state_vector()\n", "\n",
" \n", "# 我们测量输出态2048次,获得测量结果频率分布\n",
" # 我们测量输出态2048次,获得测量结果频率分布\n", "# 如果用户想获取概率分布的理论值,可以令 shots = 0\n",
" # 如果用户想获取概率分布的理论值,可以令 shots = 0\n", "cir.measure(shots = 2048, plot = True)\n",
" cir.measure(shots = 2048, plot = True)\n", "\n",
" \n", "print('我们制备出的贝尔态是:')\n",
" print('我们制备出的贝尔态是:')\n", "print(output_state.numpy())"
" print(output_state.numpy())"
] ]
}, },
{ {
...@@ -1171,7 +1147,7 @@ ...@@ -1171,7 +1147,7 @@
"### <a name=\"GD\"> 示例: 利用飞桨的梯度下降来优化多元函数</a>\n", "### <a name=\"GD\"> 示例: 利用飞桨的梯度下降来优化多元函数</a>\n",
"\n", "\n",
"\n", "\n",
"在这一节,我们学习如何用飞桨动态图机制找到一个多元函数的极小值\n", "在这一节,我们学习如何用飞桨中的优化器找到一个多元函数的极小值\n",
"\n", "\n",
"$$\n", "$$\n",
"\\mathcal{L}(\\theta_1, \\theta_2, \\theta_3)\n", "\\mathcal{L}(\\theta_1, \\theta_2, \\theta_3)\n",
...@@ -1183,11 +1159,11 @@ ...@@ -1183,11 +1159,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": 13,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:42.863949Z", "end_time": "2021-03-09T03:53:47.622260Z",
"start_time": "2021-01-09T12:48:42.262829Z" "start_time": "2021-03-09T03:53:47.183431Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -1195,7 +1171,7 @@ ...@@ -1195,7 +1171,7 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"损失函数的最小值是: 10.000000153748474\n" "损失函数的最小值是: 10.000000010745854\n"
] ]
} }
], ],
...@@ -1205,15 +1181,17 @@ ...@@ -1205,15 +1181,17 @@
"ITR = 200 # 设置迭代次数\n", "ITR = 200 # 设置迭代次数\n",
"LR = 0.5 # 设置学习速率\n", "LR = 0.5 # 设置学习速率\n",
"SEED = 1 # 固定随机数种子\n", "SEED = 1 # 固定随机数种子\n",
"paddle.seed(SEED)\n",
"\n", "\n",
"class Optimization_ex1(fluid.dygraph.Layer):\n", "class Optimization_ex1(paddle.nn.Layer):\n",
" \n", " \n",
"\n", " def __init__(self, shape, dtype='float64'):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=-5., high=5., seed=SEED), dtype='float64'):\n",
" super(Optimization_ex1, self).__init__()\n", " super(Optimization_ex1, self).__init__()\n",
" \n", " \n",
" # 初始化一个长度为 theta_size的可学习参数列表,并用 [-5, 5] 的均匀分布来填充初始值\n", " # 初始化一个长度为 theta_size的可学习参数列表,并用 [-5, 5] 的均匀分布来填充初始值\n",
" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.theta = self.create_parameter(shape=shape, \n",
" default_initializer=paddle.nn.initializer.Uniform(low=-5., high=5.), \n",
" dtype=dtype, is_bias=False)\n",
"\n", "\n",
" # 定义损失函数和前向传播机制\n", " # 定义损失函数和前向传播机制\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -1223,32 +1201,29 @@ ...@@ -1223,32 +1201,29 @@
"# 记录中间优化结果\n", "# 记录中间优化结果\n",
"loss_list = []\n", "loss_list = []\n",
"parameter_list = []\n", "parameter_list = []\n",
"\n",
"# 初始化 paddle 动态图机制\n",
"with fluid.dygraph.guard():\n",
" \n",
" # 定义网络维度\n",
" myLayer = Optimization_ex1([theta_size])\n",
" \n", " \n",
" # 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMSprop.\n", "# 定义网络维度\n",
" optimizer = fluid.optimizer.AdagradOptimizer(learning_rate = LR, parameter_list = myLayer.parameters()) \n", "myLayer = Optimization_ex1([theta_size])\n",
" \n", "\n",
" # 优化循环\n", "# 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMSprop.\n",
" for itr in range(ITR):\n", "opt = paddle.optimizer.Adam(learning_rate = LR, parameters = myLayer.parameters()) \n",
" \n", "\n",
" # 向前传播计算损失函数\n", "# 优化循环\n",
" loss = myLayer()[0]\n", "for itr in range(ITR):\n",
" \n", "\n",
" # 在动态图机制下,反向传播优化损失函数\n", " # 向前传播计算损失函数\n",
" loss.backward()\n", " loss = myLayer()[0]\n",
" optimizer.minimize(loss)\n", "\n",
" myLayer.clear_gradients()\n", " # 反向传播优化损失函数\n",
" \n", " loss.backward()\n",
" # 记录学习曲线\n", " opt.minimize(loss)\n",
" loss_list.append(loss.numpy()[0])\n", " opt.clear_grad()\n",
" parameter_list.append(myLayer.parameters()[0].numpy())\n", "\n",
" \n", " # 记录学习曲线\n",
" print('损失函数的最小值是: ', loss_list[-1])" " loss_list.append(loss.numpy()[0])\n",
" parameter_list.append(myLayer.parameters()[0].numpy())\n",
"\n",
"print('损失函数的最小值是: ', loss_list[-1])"
] ]
}, },
{ {
...@@ -1303,11 +1278,11 @@ ...@@ -1303,11 +1278,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": 14,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:43.137909Z", "end_time": "2021-03-09T03:53:50.904606Z",
"start_time": "2021-01-09T12:48:42.896539Z" "start_time": "2021-03-09T03:53:50.248060Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -1316,8 +1291,8 @@ ...@@ -1316,8 +1291,8 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"随机生成的矩阵 H 是:\n", "随机生成的矩阵 H 是:\n",
"[[0.76063331+0.j 0.06546144+0.13336071j]\n", "[[ 0.63841338-6.93889390e-18j -0.13697062-2.28212151e-01j]\n",
" [0.06546144-0.13336071j 0.23936669+0.j ]] \n", " [-0.13697062+2.28212151e-01j 0.36158662+0.00000000e+00j]] \n",
"\n", "\n",
"不出所料,H 的特征值是:\n", "不出所料,H 的特征值是:\n",
"[0.2 0.8]\n" "[0.2 0.8]\n"
...@@ -1347,11 +1322,11 @@ ...@@ -1347,11 +1322,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": 15,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:43.155166Z", "end_time": "2021-03-09T03:53:50.916504Z",
"start_time": "2021-01-09T12:48:43.146544Z" "start_time": "2021-03-09T03:53:50.908516Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -1359,10 +1334,10 @@ ...@@ -1359,10 +1334,10 @@
"# 超参数设置\n", "# 超参数设置\n",
"theta_size = 3 # 设置 theta 维度\n", "theta_size = 3 # 设置 theta 维度\n",
"num_qubits = 1 # 设置量子比特数\n", "num_qubits = 1 # 设置量子比特数\n",
"ITR = 10 # 设置迭代次数\n", "ITR = 50 # 设置迭代次数\n",
"LR = 0.8 # 设置学习速率\n", "LR = 0.5 # 设置学习速率\n",
"SEED = 1 # 固定theta参数的随机数种子\n", "SEED = 1 # 固定theta参数的随机数种子\n",
"\n", "paddle.seed(SEED)\n",
"\n", "\n",
"# 单独设置电路模块\n", "# 单独设置电路模块\n",
"def U_theta(theta):\n", "def U_theta(theta):\n",
...@@ -1379,24 +1354,25 @@ ...@@ -1379,24 +1354,25 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 13, "execution_count": 16,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:43.179953Z", "end_time": "2021-03-09T03:53:54.556150Z",
"start_time": "2021-01-09T12:48:43.161434Z" "start_time": "2021-03-09T03:53:54.489747Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Optimization_ex2(fluid.dygraph.Layer):\n", "class Optimization_ex2(paddle.nn.Layer):\n",
" \n", " \n",
"\n", " def __init__(self, shape, dtype='float64'):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0., high=2*np.pi, seed=SEED), dtype='float64'):\n",
" super(Optimization_ex2, self).__init__()\n", " super(Optimization_ex2, self).__init__()\n",
" \n", " \n",
" # 初始化一个长度为 theta_size的可学习参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n", " # 初始化一个长度为 theta_size的可学习参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n",
" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.theta = self.create_parameter(shape=shape, \n",
" self.H = fluid.dygraph.to_variable(H)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0., high=2*np.pi), \n",
" dtype=dtype, is_bias=False)\n",
" self.H = paddle.to_tensor(H)\n",
" \n", " \n",
" # 定义损失函数和前向传播机制\n", " # 定义损失函数和前向传播机制\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -1408,18 +1384,18 @@ ...@@ -1408,18 +1384,18 @@
" U_dagger = dagger(U)\n", " U_dagger = dagger(U)\n",
" \n", " \n",
" # 计算损失函数函数\n", " # 计算损失函数函数\n",
" loss = matmul(U_dagger, matmul(self.H, U)).real[0][0]\n", " loss = paddle.real(matmul(U_dagger, matmul(self.H, U)))[0][0]\n",
" \n", " \n",
" return loss" " return loss"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 14, "execution_count": 17,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:43.581225Z", "end_time": "2021-03-09T03:53:59.114893Z",
"start_time": "2021-01-09T12:48:43.201135Z" "start_time": "2021-03-09T03:53:58.381044Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -1427,50 +1403,47 @@ ...@@ -1427,50 +1403,47 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 0 loss: 0.7653\n", "iter: 0 loss: 0.6550\n",
"iter: 1 loss: 0.5138\n", "iter: 5 loss: 0.4527\n",
"iter: 2 loss: 0.2556\n", "iter: 10 loss: 0.2951\n",
"iter: 3 loss: 0.2068\n", "iter: 15 loss: 0.2330\n",
"iter: 4 loss: 0.2030\n", "iter: 20 loss: 0.2108\n",
"iter: 5 loss: 0.2015\n", "iter: 25 loss: 0.2033\n",
"iter: 6 loss: 0.2007\n", "iter: 30 loss: 0.2010\n",
"iter: 7 loss: 0.2004\n", "iter: 35 loss: 0.2003\n",
"iter: 8 loss: 0.2002\n", "iter: 40 loss: 0.2001\n",
"iter: 9 loss: 0.2001\n", "iter: 45 loss: 0.2000\n",
"损失函数的最小值是: 0.20007871016474926\n" "损失函数的最小值是: 0.20000807961972783\n"
] ]
} }
], ],
"source": [ "source": [
"loss_list = []\n", "loss_list = []\n",
"parameter_list = []\n", "parameter_list = []\n",
" \n",
"myLayer = Optimization_ex2([theta_size])\n",
"\n", "\n",
"# 这里采用 SGD 优化器\n",
"opt = paddle.optimizer.SGD(learning_rate = LR, parameters = myLayer.parameters()) \n",
"\n", "\n",
"# 初始化paddle动态图机制\n", "# 优化循环\n",
"with fluid.dygraph.guard():\n", "for itr in range(ITR):\n",
" \n", "\n",
" myLayer = Optimization_ex2([theta_size])\n", " # 前向传播计算损失函数\n",
" \n", " loss = myLayer()[0]\n",
" # 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMS prop.\n", "\n",
" optimizer = fluid.optimizer.AdagradOptimizer(learning_rate = LR, parameter_list = myLayer.parameters()) \n", " # 反向传播极小化损失函数\n",
" \n", " loss.backward()\n",
" # 优化循环\n", " opt.minimize(loss)\n",
" for itr in range(ITR):\n", " opt.clear_grad()\n",
" \n", "\n",
" # 前向传播计算损失函数\n", " # 记录学习曲线\n",
" loss = myLayer()[0]\n", " loss_list.append(loss.numpy()[0])\n",
" \n", " parameter_list.append(myLayer.parameters()[0].numpy())\n",
" # 在动态图机制下,反向传播极小化损失函数\n", " if itr % 5 == 0:\n",
" loss.backward()\n",
" optimizer.minimize(loss)\n",
" myLayer.clear_gradients()\n",
" \n",
" # 记录学习曲线\n",
" loss_list.append(loss.numpy()[0])\n",
" parameter_list.append(myLayer.parameters()[0].numpy())\n",
" print('iter:', itr, ' loss: %.4f' % loss.numpy())\n", " print('iter:', itr, ' loss: %.4f' % loss.numpy())\n",
" \n", "\n",
" print('损失函数的最小值是: ', loss_list[-1])" "print('损失函数的最小值是: ', loss_list[-1])"
] ]
}, },
{ {
...@@ -1531,11 +1504,11 @@ ...@@ -1531,11 +1504,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 15, "execution_count": 18,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:43.603696Z", "end_time": "2021-03-09T03:54:03.717323Z",
"start_time": "2021-01-09T12:48:43.592558Z" "start_time": "2021-03-09T03:54:03.709869Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -1550,9 +1523,9 @@ ...@@ -1550,9 +1523,9 @@
"# 超参数设置\n", "# 超参数设置\n",
"num_qubits = 2\n", "num_qubits = 2\n",
"theta_size = 4\n", "theta_size = 4\n",
"ITR = 10\n", "ITR = 60\n",
"LR = 0.5\n", "LR = 0.4\n",
"SEED = 1 \n", "SEED = 999 \n",
"\n", "\n",
"# 把记录的关于哈密顿量的信息转化为矩阵表示\n", "# 把记录的关于哈密顿量的信息转化为矩阵表示\n",
"H_matrix = pauli_str_to_matrix(H_info, num_qubits)" "H_matrix = pauli_str_to_matrix(H_info, num_qubits)"
...@@ -1560,24 +1533,25 @@ ...@@ -1560,24 +1533,25 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 16, "execution_count": 19,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:43.719137Z", "end_time": "2021-03-09T03:54:04.655091Z",
"start_time": "2021-01-09T12:48:43.608167Z" "start_time": "2021-03-09T03:54:04.643511Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class vqe_demo(fluid.dygraph.Layer):\n", "class vqe_demo(paddle.nn.Layer):\n",
" \n", " \n",
"\n", " def __init__(self, shape, dtype='float64'):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0., high=2*np.pi, seed=SEED), dtype='float64'):\n",
" super(vqe_demo, self).__init__()\n", " super(vqe_demo, self).__init__()\n",
" \n", " \n",
" # 初始化一个长度为theta_size的可学习参数列表,并用[0, 2*pi]的均匀分布来填充初始值\n", " # 初始化一个长度为theta_size的可学习参数列表,并用[0, 2*pi]的均匀分布来填充初始值\n",
" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.theta = self.create_parameter(shape=shape, \n",
" self.H = fluid.dygraph.to_variable(H)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0., high=2*np.pi), \n",
" dtype=dtype, is_bias=False)\n",
" self.H = paddle.to_tensor(H)\n",
" \n", " \n",
" # 定义损失函数和前向传播机制\n", " # 定义损失函数和前向传播机制\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -1604,11 +1578,11 @@ ...@@ -1604,11 +1578,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 17, "execution_count": 20,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:48:46.185285Z", "end_time": "2021-03-09T03:54:17.622644Z",
"start_time": "2021-01-09T12:48:43.831438Z" "start_time": "2021-03-09T03:54:08.611202Z"
}, },
"colab": { "colab": {
"base_uri": "https://localhost:8080/", "base_uri": "https://localhost:8080/",
...@@ -1623,17 +1597,13 @@ ...@@ -1623,17 +1597,13 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 0 loss: 0.3195\n", "iter: 0 loss: 0.7363\n",
"iter: 1 loss: -0.3615\n", "iter: 10 loss: -0.5727\n",
"iter: 2 loss: -0.6528\n", "iter: 20 loss: -0.7474\n",
"iter: 3 loss: -0.7420\n", "iter: 30 loss: -0.8101\n",
"iter: 4 loss: -0.7813\n", "iter: 40 loss: -0.8154\n",
"iter: 5 loss: -0.8022\n", "iter: 50 loss: -0.8225\n",
"iter: 6 loss: -0.8130\n", "计算得到的基态能量是: -0.824229008050201\n",
"iter: 7 loss: -0.8187\n",
"iter: 8 loss: -0.8216\n",
"iter: 9 loss: -0.8231\n",
"计算得到的基态能量是: -0.8230721264692568\n",
"真实的基态能量为: -0.8246211251235321\n" "真实的基态能量为: -0.8246211251235321\n"
] ]
} }
...@@ -1642,35 +1612,32 @@ ...@@ -1642,35 +1612,32 @@
"loss_list = []\n", "loss_list = []\n",
"parameter_list = []\n", "parameter_list = []\n",
"\n", "\n",
"# 定义网络维度\n",
"vqe = vqe_demo([theta_size])\n",
"\n", "\n",
"# 初始化paddle动态图机制\n", "# 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMS prop.\n",
"with fluid.dygraph.guard():\n", "opt = paddle.optimizer.Adam(learning_rate = LR, parameters = vqe.parameters()) \n",
" \n", "\n",
" # 定义网络维度\n", "# 优化循环\n",
" vqe = vqe_demo([theta_size])\n", "for itr in range(ITR):\n",
" \n", "\n",
" # 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMS prop.\n", " # 前向传播计算损失函数\n",
" optimizer = fluid.optimizer.AdagradOptimizer(learning_rate = LR, parameter_list = vqe.parameters()) \n", " loss = vqe()\n",
" \n", "\n",
" # 优化循环\n", " # 反向传播极小化损失函数\n",
" for itr in range(ITR):\n", " loss.backward()\n",
" \n", " opt.minimize(loss)\n",
" # 前向传播计算损失函数\n", " opt.clear_grad()\n",
" loss = vqe()\n", "\n",
" \n", " # 记录学习曲线\n",
" # 在动态图机制下,反向传播极小化损失函数\n", " loss_list.append(loss.numpy()[0])\n",
" loss.backward()\n", " parameter_list.append(vqe.parameters()[0].numpy())\n",
" optimizer.minimize(loss)\n", " if itr % 10 == 0:\n",
" vqe.clear_gradients()\n",
" \n",
" # 记录学习曲线\n",
" loss_list.append(loss.numpy()[0])\n",
" parameter_list.append(vqe.parameters()[0].numpy())\n",
" print('iter:', itr, ' loss: %.4f' % loss.numpy())\n", " print('iter:', itr, ' loss: %.4f' % loss.numpy())\n",
" \n", "\n",
" \n", "\n",
" print('计算得到的基态能量是: ', loss_list[-1])\n", "print('计算得到的基态能量是: ', loss_list[-1])\n",
" print('真实的基态能量为: ', np.linalg.eigh(H_matrix)[0][0])" "print('真实的基态能量为: ', np.linalg.eigh(H_matrix)[0][0])"
] ]
}, },
{ {
...@@ -1737,7 +1704,7 @@ ...@@ -1737,7 +1704,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.8" "version": "3.7.0"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
...@@ -1756,6 +1723,35 @@ ...@@ -1756,6 +1723,35 @@
}, },
"toc_section_display": true, "toc_section_display": true,
"toc_window_display": true "toc_window_display": true
},
"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
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
"- PaddlePaddle optimizer tutorial\n", "- PaddlePaddle optimizer tutorial\n",
"- A case study on quantum machine learning - Variational Quantum Eigensolver (VQE)\n", "- A case study on quantum machine learning - Variational Quantum Eigensolver (VQE)\n",
"\n", "\n",
"**Latest version updated on:** Jan. 9th, 2021 by Paddle Quantum developers.\n", "**Latest version updated on:** Mar. 2nd, 2021 by Paddle Quantum developers.\n",
"\n", "\n",
"---\n" "---\n"
] ]
...@@ -296,8 +296,8 @@ ...@@ -296,8 +296,8 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:57:05.944723Z", "end_time": "2021-03-09T03:55:14.848783Z",
"start_time": "2021-01-09T12:57:02.038199Z" "start_time": "2021-03-09T03:55:10.779109Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -313,32 +313,34 @@ ...@@ -313,32 +313,34 @@
], ],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"from paddle import fluid\n", "import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import dagger, random_pauli_str_generator, pauli_str_to_matrix\n",
"from paddle_quantum.state import vec, vec_random, density_op, density_op_random, completely_mixed_computational\n",
"\n",
"from paddle import matmul, transpose, trace \n",
"\n",
"\n", "\n",
"# Set the angle parameter theta = pi\n", "# Set the angle parameter theta = pi\n",
"theta = np.array([np.pi])\n", "theta = np.array([np.pi])\n",
"\n",
"# Initiate Paddle dynamic graph mode\n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" # We need to convert numpy.ndarray to variable supported in Paddle dynamic graph mode\n", "# We need to convert numpy.ndarray to Tensor in PaddlePaddle\n",
" theta = fluid.dygraph.to_variable(theta)\n", "theta = paddle.to_tensor(theta)\n",
" \n", "\n",
" # Set the number of qubits required for calculation\n", "# Set the number of qubits required for calculation\n",
" num_qubits = 1\n", "num_qubits = 1\n",
" \n", "\n",
" # Initialize our single-bit quantum circuit\n", "# Initialize our single-bit quantum circuit\n",
" cir = UAnsatz(num_qubits)\n", "cir = UAnsatz(num_qubits)\n",
" \n", "\n",
" # Apply an Rx rotation gate to the first qubit (q0), the angle is pi\n", "# Apply an Rx rotation gate to the first qubit (q0), the angle is pi\n",
" which_qubit = 0\n", "which_qubit = 0\n",
" cir.rx(theta, which_qubit)\n", "cir.rx(theta, which_qubit)\n",
" \n", "\n",
" # Convert to numpy.ndarray\n", "# Convert to numpy.ndarray\n",
" # Print out this quantum gate\n", "# Print out this quantum gate\n",
" print('The matrix representation of quantum gate is:')\n", "print('The matrix representation of quantum gate is:')\n",
" print(cir.U.numpy())" "print(cir.U.numpy())"
] ]
}, },
{ {
...@@ -368,17 +370,22 @@ ...@@ -368,17 +370,22 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": {}, "metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:55:00.653853Z",
"start_time": "2021-03-09T03:55:00.404797Z"
},
"scrolled": true
},
"outputs": [], "outputs": [],
"source": [ "source": [
"theta = \"your code\"\n", "theta = \"your code\"\n",
"\n", " \n",
"with fluid.dygraph.guard(): \n", "theta = paddle.to_tensor(theta)\n",
" theta = fluid.dygraph.to_variable(theta)\n", "num_qubits = 1\n",
" num_qubits = 1\n", "cir = UAnsatz(\"your code\")\n",
" cir = UAnsatz(\"your code\")\n", "cir.ry(\"your code\")\n",
" cir.ry(\"your code\")\n", "print(cir.U.numpy())"
" print(cir.U.numpy())"
] ]
}, },
{ {
...@@ -420,11 +427,11 @@ ...@@ -420,11 +427,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:58:40.113133Z", "end_time": "2021-03-09T03:55:17.952285Z",
"start_time": "2021-01-09T12:58:40.081753Z" "start_time": "2021-03-09T03:55:17.912517Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -441,36 +448,29 @@ ...@@ -441,36 +448,29 @@
} }
], ],
"source": [ "source": [
"import numpy as np\n",
"from paddle import fluid\n",
"from paddle_quantum.circuit import UAnsatz\n",
"\n",
"# Set the angle parameter theta\n", "# Set the angle parameter theta\n",
"theta = np.full([4], np.pi)\n", "theta = np.full([4], np.pi)\n",
"\n",
"# Start Paddle dynamic graph mode\n",
"with fluid.dygraph.guard():\n",
" \n",
" # We need to convert numpy.ndarray to variable supported in Paddle dynamic graph mode\n",
" theta = fluid.dygraph.to_variable(theta)\n",
" \n", " \n",
" # Initialize the quantum circuit\n", "# We need to convert numpy.ndarray to Tensor in PaddlePaddle\n",
" num_qubits = 2\n", "theta = paddle.to_tensor(theta)\n",
" cir = UAnsatz(num_qubits)\n",
" \n",
" # Add single-qubit rotation gates\n",
" cir.ry(theta[0], 0)\n",
" cir.ry(theta[1], 1)\n",
"\n", "\n",
" # Add two-qubit gate\n", "# Initialize the quantum circuit\n",
" cir.cnot([0, 1])\n", "num_qubits = 2\n",
"cir = UAnsatz(num_qubits)\n",
"\n", "\n",
" # Add single-qubit rotation gates\n", "# Add single-qubit rotation gates\n",
" cir.ry(theta[2], 0)\n", "cir.ry(theta[0], 0)\n",
" cir.ry(theta[3], 1)\n", "cir.ry(theta[1], 1)\n",
" \n", "\n",
" print('The matrix representation of the quantum neural network U(theta=pi) in the figure is:')\n", "# Add two-qubit gate\n",
" print(cir.U.numpy().real)" "cir.cnot([0, 1])\n",
"\n",
"# Add single-qubit rotation gates\n",
"cir.ry(theta[2], 0)\n",
"cir.ry(theta[3], 1)\n",
"\n",
"print('The matrix representation of the quantum neural network U(theta=pi) in the figure is:')\n",
"print(cir.U.numpy().real)"
] ]
}, },
{ {
...@@ -501,28 +501,32 @@ ...@@ -501,28 +501,32 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 5,
"metadata": {}, "metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:55:18.945226Z",
"start_time": "2021-03-09T03:55:18.935212Z"
}
},
"outputs": [], "outputs": [],
"source": [ "source": [
"theta = np.full([6], np.pi)\n", "theta = np.full([6], np.pi)\n",
"with fluid.dygraph.guard():\n",
" \n",
" theta = fluid.dygraph.to_variable(theta)\n",
" \n",
" num_qubits = 3\n",
" cir = UAnsatz(num_qubits)\n",
" \n",
" cir.ry(theta[0], 0)\n",
" cir.ry(theta[1], 1)\n",
" cir.ry(theta[2], 2)\n",
" \n",
" cir.cnot([0, 1])\n",
" cir.cnot([1, 2])\n",
"\n", "\n",
" cir.ry(theta[3], 0)\n", "theta = paddle.to_tensor(theta)\n",
" cir.ry(theta[4], 1)\n", "\n",
" cir.ry(theta[5], 2)" "num_qubits = 3\n",
"cir = UAnsatz(num_qubits)\n",
"\n",
"cir.ry(theta[0], 0)\n",
"cir.ry(theta[1], 1)\n",
"cir.ry(theta[2], 2)\n",
"\n",
"cir.cnot([0, 1])\n",
"cir.cnot([1, 2])\n",
"\n",
"cir.ry(theta[3], 0)\n",
"cir.ry(theta[4], 1)\n",
"cir.ry(theta[5], 2)"
] ]
}, },
{ {
...@@ -546,18 +550,18 @@ ...@@ -546,18 +550,18 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:59:37.481620Z", "end_time": "2021-03-09T03:55:20.402902Z",
"start_time": "2021-01-09T12:59:37.040582Z" "start_time": "2021-03-09T03:55:19.838729Z"
}, },
"scrolled": true "scrolled": false
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -570,37 +574,34 @@ ...@@ -570,37 +574,34 @@
], ],
"source": [ "source": [
"N = 3 # Set the number of qubits\n", "N = 3 # Set the number of qubits\n",
" \n",
"# Initialize the quantum circuit\n",
"cir = UAnsatz(N)\n",
"\n", "\n",
"# Start PaddlePaddle dynamic graph mode\n", "# Apply Hadamard gate on each qubit\n",
"with fluid.dygraph.guard():\n", "cir.superposition_layer()\n",
" \n", "\n",
" # Initialize the quantum circuit\n", "# Prepare output state\n",
" cir = UAnsatz(N)\n", "# If the user does not enter the initial quantum state, the default initial is |00..0>\n",
" \n", "final_state = cir.run_state_vector()\n",
" # Apply Hadamard gate on each qubit\n", "\n",
" cir.superposition_layer()\n", "# Get the theoretical value of the probability distribution, set shots = 0\n",
" \n", "res = cir.measure(shots = 0, plot = True)"
" # Prepare output state\n",
" # If the user does not enter the initial quantum state, the default initial is |00..0>\n",
" final_state = cir.run_state_vector()\n",
" \n",
" # Get the theoretical value of the probability distribution, set shots = 0\n",
" cir.measure(shots = 0, plot = True)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T12:59:50.443828Z", "end_time": "2021-03-09T03:55:21.071722Z",
"start_time": "2021-01-09T12:59:50.101308Z" "start_time": "2021-03-09T03:55:20.413129Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -613,22 +614,19 @@ ...@@ -613,22 +614,19 @@
], ],
"source": [ "source": [
"N = 3 # Set the number of qubits\n", "N = 3 # Set the number of qubits\n",
"\n",
"# Start PaddlePaddle dynamic graph mode\n",
"with fluid.dygraph.guard():\n",
" \n",
" # Initialize the quantum circuit\n",
" cir = UAnsatz(N)\n",
" \n", " \n",
" # Apply Ry(pi/4) rotation gate on each qubit\n", "# Initialize the quantum circuit\n",
" cir.weak_superposition_layer()\n", "cir = UAnsatz(N)\n",
" \n", "\n",
" # Prepare output state\n", "# Apply Ry(pi/4) rotation gate on each qubit\n",
" # If the user does not enter the initial quantum state, the default initial state is |00..0>\n", "cir.weak_superposition_layer()\n",
" final_state = cir.run_state_vector()\n", "\n",
" \n", "# Prepare output state\n",
" # Get the theoretical value of the probability distribution, set shots = 0\n", "# If the user does not enter the initial quantum state, the default initial state is |00..0>\n",
" cir.measure(shots = 0, plot = True)" "final_state = cir.run_state_vector()\n",
"\n",
"# Get the theoretical value of the probability distribution, set shots = 0\n",
"res = cir.measure(shots = 0, plot = True)"
] ]
}, },
{ {
...@@ -675,17 +673,17 @@ ...@@ -675,17 +673,17 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:00:30.035538Z", "end_time": "2021-03-09T03:55:24.555510Z",
"start_time": "2021-01-09T13:00:29.585215Z" "start_time": "2021-03-09T03:55:24.030742Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -700,25 +698,22 @@ ...@@ -700,25 +698,22 @@
"N = 4 # Set the number of qubits\n", "N = 4 # Set the number of qubits\n",
"DEPTH = 6 # Set the quantum circuit depth\n", "DEPTH = 6 # Set the quantum circuit depth\n",
"theta = np.random.randn(DEPTH, N, 3)\n", "theta = np.random.randn(DEPTH, N, 3)\n",
"\n",
"# Start Paddle dynamic graph mode\n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" # We need to convert numpy.ndarray to variable supported in Paddle dynamic graph mode\n", "# We need to convert numpy.ndarray to Tensor in PaddlePaddle\n",
" theta = fluid.dygraph.to_variable(theta)\n", "theta = paddle.to_tensor(theta)\n",
" \n", "\n",
" # Initialize the quantum circuit\n", "# Initialize the quantum circuit\n",
" cir = UAnsatz(N)\n", "cir = UAnsatz(N)\n",
" \n", "\n",
" # Add a complex strong entanglement structure QNN with depth D = 6 {Rz+Ry+Rz/U3 + CNOT's}\n", "# Add a complex strong entanglement structure QNN with depth D = 6 {Rz+Ry+Rz/U3 + CNOT's}\n",
" cir.complex_entangled_layer(theta, DEPTH)\n", "cir.complex_entangled_layer(theta, DEPTH)\n",
" \n", "\n",
" # Prepare output state\n", "# Prepare output state\n",
" # If the user does not enter the initial quantum state, the default initial is |00..0>\n", "# If the user does not enter the initial quantum state, the default initial is |00..0>\n",
" final_state = cir.run_state_vector()\n", "final_state = cir.run_state_vector()\n",
" \n", "\n",
" # Measure the output state [0, 1, 2] qubits 2048 times, and count the frequency of the measurement results\n", "# Measure the output state [0, 1, 2] qubits 2048 times, and count the frequency of the measurement results\n",
" cir.measure(shots = 2048, which_qubits = [0, 1, 2], plot = True)" "res = cir.measure(shots = 2048, which_qubits = [0, 1, 2], plot = True)"
] ]
}, },
{ {
...@@ -743,11 +738,11 @@ ...@@ -743,11 +738,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 9,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:02:13.332713Z", "end_time": "2021-03-09T03:55:44.714297Z",
"start_time": "2021-01-09T13:01:13.592149Z" "start_time": "2021-03-09T03:55:28.589382Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -755,17 +750,12 @@ ...@@ -755,17 +750,12 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"[[ 0.00072194+0.j 0.00044133+0.j 0.00064311+0.j ... -0.00045617+0.j\n", "[[ 1.08337247e-03+0.j 1.00193659e-04+0.j 1.16958435e-03+0.j ...\n",
" 0.00025925+0.j 0.00080118+0.j]]\n" " -6.02439155e-04+0.j 7.83088243e-05+0.j 6.42545561e-05+0.j]]\n"
] ]
} }
], ],
"source": [ "source": [
"import numpy as np\n",
"from paddle import fluid\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.state import vec, vec_random\n",
"\n",
"N = 20 # Set the number of qubits\n", "N = 20 # Set the number of qubits\n",
"DEPTH = 6 # Set the quantum circuit depth\n", "DEPTH = 6 # Set the quantum circuit depth\n",
"theta = np.random.randn(DEPTH, N, 1)\n", "theta = np.random.randn(DEPTH, N, 1)\n",
...@@ -774,24 +764,21 @@ ...@@ -774,24 +764,21 @@
"initial_state1 = vec(N)\n", "initial_state1 = vec(N)\n",
"# Call the built-in random quantum state |psi>\n", "# Call the built-in random quantum state |psi>\n",
"initial_state2 = vec_random(N)\n", "initial_state2 = vec_random(N)\n",
"\n",
"# Start Paddle dynamic graph mode\n",
"with fluid.dygraph.guard():\n",
" \n",
" # We need to convert numpy.ndarray to variable supported in PaddlePaddle dynamic graph mode\n",
" theta = fluid.dygraph.to_variable(theta)\n",
" initial_state = fluid.dygraph.to_variable(initial_state1)\n",
" \n",
" # Initialize the quantum circuit\n",
" cir = UAnsatz(N)\n",
" \n", " \n",
" # Add a real entanglement structure QNN {Ry+CNOT's} with depth of DEPTH\n", "# We need to convert numpy.ndarray to Tensor in PaddlePaddle\n",
" cir.real_entangled_layer(theta, DEPTH)\n", "theta = paddle.to_tensor(theta)\n",
" \n", "initial_state = paddle.to_tensor(initial_state1)\n",
" # Prepare output state\n", "\n",
" # If the user does not enter the initial quantum state, the default initial state is |00..0>\n", "# Initialize the quantum circuit\n",
" final_state = cir.run_state_vector(initial_state)\n", "cir = UAnsatz(N)\n",
" print(final_state.numpy())" "\n",
"# Add a real entanglement structure QNN {Ry+CNOT's} with depth of DEPTH\n",
"cir.real_entangled_layer(theta, DEPTH)\n",
"\n",
"# Prepare output state\n",
"# If the user does not enter the initial quantum state, the default initial state is |00..0>\n",
"final_state = cir.run_state_vector(initial_state)\n",
"print(final_state.numpy())"
] ]
}, },
{ {
...@@ -814,11 +801,11 @@ ...@@ -814,11 +801,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 10,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:02:13.431007Z", "end_time": "2021-03-09T03:55:45.027724Z",
"start_time": "2021-01-09T13:02:13.337255Z" "start_time": "2021-03-09T03:55:44.723567Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -826,20 +813,14 @@ ...@@ -826,20 +813,14 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"[[ 2.58020326e-01+0.j -3.54982418e-01+0.j 2.55776343e-01+0.j\n", "[[ 0.86516792+0.j 0.08806816+0.j -0.21659148+0.j 0.2489669 +0.j]\n",
" 3.43259769e-03+0.j]\n", " [ 0.08806816+0.j 0.00896474+0.j -0.02204753+0.j 0.02534312+0.j]\n",
" [-3.54982418e-01+0.j 4.88382132e-01+0.j -3.51895163e-01+0.j\n", " [-0.21659148+0.j -0.02204753+0.j 0.05422285+0.j -0.06232791+0.j]\n",
" -4.72254201e-03+0.j]\n", " [ 0.2489669 +0.j 0.02534312+0.j -0.06232791+0.j 0.0716445 +0.j]]\n"
" [ 2.55776343e-01+0.j -3.51895163e-01+0.j 2.53551876e-01+0.j\n",
" 3.40274466e-03+0.j]\n",
" [ 3.43259769e-03+0.j -4.72254201e-03+0.j 3.40274466e-03+0.j\n",
" 4.56658865e-05+0.j]]\n"
] ]
} }
], ],
"source": [ "source": [
"from paddle_quantum.state import density_op, density_op_random, completely_mixed_computational\n",
"\n",
"N = 2 # Set the number of qubits\n", "N = 2 # Set the number of qubits\n",
"DEPTH = 6 # Set the quantum circuit depth\n", "DEPTH = 6 # Set the quantum circuit depth\n",
"theta = np.random.randn(DEPTH, N, 1)\n", "theta = np.random.randn(DEPTH, N, 1)\n",
...@@ -851,23 +832,20 @@ ...@@ -851,23 +832,20 @@
"# Call the complete mixed state under the built-in calculation base\n", "# Call the complete mixed state under the built-in calculation base\n",
"initial_state3 = completely_mixed_computational(N)\n", "initial_state3 = completely_mixed_computational(N)\n",
"\n", "\n",
"# Start Paddle dynamic graph mode\n", "# We need to convert numpy.ndarray to Tensor in PaddlePaddle\n",
"with fluid.dygraph.guard():\n", "theta = paddle.to_tensor(theta)\n",
" \n", "initial_state = paddle.to_tensor(initial_state1)\n",
" # We need to convert numpy.ndarray to variable supported in PaddlePaddle dynamic graph mode\n", "\n",
" theta = fluid.dygraph.to_variable(theta)\n", "# Initialize the quantum circuit\n",
" initial_state = fluid.dygraph.to_variable(initial_state1)\n", "cir = UAnsatz(N)\n",
" \n", "\n",
" # Initialize the quantum circuit\n", "# Add a real number strong entanglement structure QNN {Ry+CNOT's} with depth of DEPTH\n",
" cir = UAnsatz(N)\n", "cir.real_entangled_layer(theta, DEPTH)\n",
" \n", "\n",
" # Add a real number strong entanglement structure QNN {Ry+CNOT's} with depth of DEPTH\n", "# Prepare output state\n",
" cir.real_entangled_layer(theta, DEPTH)\n", "# If the user does not enter the initial quantum state, the default initial is |00..0><00..0|\n",
" \n", "final_state = cir.run_density_matrix(initial_state)\n",
" # Prepare output state\n", "print(final_state.numpy())"
" # If the user does not enter the initial quantum state, the default initial is |00..0><00..0|\n",
" final_state = cir.run_density_matrix(initial_state)\n",
" print(final_state.numpy())"
] ]
}, },
{ {
...@@ -897,17 +875,17 @@ ...@@ -897,17 +875,17 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": 11,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:02:13.775333Z", "end_time": "2021-03-09T03:55:49.403917Z",
"start_time": "2021-01-09T13:02:13.434980Z" "start_time": "2021-03-09T03:55:48.909563Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -927,23 +905,20 @@ ...@@ -927,23 +905,20 @@
} }
], ],
"source": [ "source": [
"# Start Paddle dynamic graph mode\n", "# Initialize the quantum circuit\n",
"with fluid.dygraph.guard():\n", "cir = UAnsatz(2)\n",
" \n",
" # Initialize the quantum circuit\n",
" cir = UAnsatz(2)\n",
"\n", "\n",
" # Add quantum gates\n", "# Add quantum gates\n",
" cir.h(0)\n", "cir.h(0)\n",
" cir.cnot([0, 1])\n", "cir.cnot([0, 1])\n",
" \n", "\n",
" # If the user does not enter the initial quantum state, the default initial is |00..0>\n", "# If the user does not enter the initial quantum state, the default initial is |00..0>\n",
" output_state = cir.run_state_vector()\n", "output_state = cir.run_state_vector()\n",
" \n", "\n",
" # We measure the output state 2048 times and obtain the frequency distribution of the measurement results\n", "# We measure the output state 2048 times and obtain the frequency distribution of the measurement results\n",
" cir.measure(shots = 2048, plot = True)\n", "cir.measure(shots = 2048, plot = True)\n",
" \n", "\n",
" print('The Bell state is:\\n', output_state.numpy())" "print('The Bell state is:\\n', output_state.numpy())"
] ]
}, },
{ {
...@@ -962,7 +937,7 @@ ...@@ -962,7 +937,7 @@
"## Example: Using gradient descent in PaddlePaddle to optimize multivariable functions\n", "## Example: Using gradient descent in PaddlePaddle to optimize multivariable functions\n",
"\n", "\n",
"\n", "\n",
"In this section, we will learn how to use the PaddlePaddle dynamic computational graph to find the minimum value of a multivariable function, for example,\n", "In this section, we will learn how to use an optimizer in PaddlePaddle to find the minimum value of a multivariable function, for example,\n",
"\n", "\n",
"$$\n", "$$\n",
"\\mathcal{L}(\\theta_1, \\theta_2, \\theta_3)\n", "\\mathcal{L}(\\theta_1, \\theta_2, \\theta_3)\n",
...@@ -975,11 +950,11 @@ ...@@ -975,11 +950,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": 12,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:03:57.626603Z", "end_time": "2021-03-09T03:56:01.481603Z",
"start_time": "2021-01-09T13:03:57.398028Z" "start_time": "2021-03-09T03:56:01.040146Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -987,31 +962,28 @@ ...@@ -987,31 +962,28 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"The minimum value of the loss function is: 10.000000020981819\n" "The minimum value of the loss function is: 10.000000010745854\n"
] ]
} }
], ],
"source": [ "source": [
"import numpy as np\n",
"from paddle import fluid\n",
"from paddle.complex import matmul\n",
"from paddle_quantum.utils import dagger\n",
"\n",
"# Set hyper parameter\n", "# Set hyper parameter\n",
"theta_size = 3\n", "theta_size = 3\n",
"ITR = 200 # Set the number of iterations\n", "ITR = 200 # Set the number of iterations\n",
"LR = 0.5 # Set the learning rate\n", "LR = 0.5 # Set the learning rate\n",
"SEED = 1 # Fix random number seed\n", "SEED = 1 # Fix random number seed\n",
"paddle.seed(SEED)\n",
"\n", "\n",
"class Optimization_ex1(fluid.dygraph.Layer):\n", "class Optimization_ex1(paddle.nn.Layer):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " \n",
" low=-5., high=5., seed=SEED), dtype='float64'):\n", " def __init__(self, shape, dtype='float64'):\n",
" super(Optimization_ex1, self).__init__()\n", " super(Optimization_ex1, self).__init__()\n",
" \n", " \n",
" # Initialize a list of learnable parameters with length theta_size\n", " # Initialize a list of learnable parameters with length theta_size\n",
" # Use the uniform distribution of [-5, 5] to fill the initial value\n", " # Use the uniform distribution of [-5, 5] to fill the initial value\n",
" self.theta = self.create_parameter(\n", " self.theta = self.create_parameter(shape=shape, \n",
" shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=-5., high=5.), \n",
" dtype=dtype, is_bias=False)\n",
"\n", "\n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -1021,34 +993,31 @@ ...@@ -1021,34 +993,31 @@
"# Record intermediate optimization results\n", "# Record intermediate optimization results\n",
"loss_list = []\n", "loss_list = []\n",
"parameter_list = []\n", "parameter_list = []\n",
"\n",
"# Initialize paddle dynamic computational graph \n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" # Define network dimensions\n", "# Define network dimensions\n",
" myLayer = Optimization_ex1([theta_size])\n", "myLayer = Optimization_ex1([theta_size])\n",
" \n", "\n",
" # Use Adam optimizer to get relatively good convergence\n", "# Use Adam optimizer to get relatively good convergence\n",
" # Of course you can change to SGD or RMSprop.\n", "# Of course you can change to SGD or RMSprop.\n",
" optimizer = fluid.optimizer.AdamOptimizer(\n", "opt = paddle.optimizer.Adam(\n",
" learning_rate = LR, parameter_list = myLayer.parameters())\n", "learning_rate = LR, parameters = myLayer.parameters())\n",
" \n", "\n",
" # Iteration of optimization\n", "# Iteration of optimization\n",
" for itr in range(ITR):\n", "for itr in range(ITR):\n",
" \n", "\n",
" # Forward propagation calculates the loss function\n", " # Forward propagation calculates the loss function\n",
" loss = myLayer()[0]\n", " loss = myLayer()[0]\n",
" \n", "\n",
" # Under the dynamic graph mode, backpropagation optimizes the loss function\n", " # Backpropagation optimizes the loss function\n",
" loss.backward()\n", " loss.backward()\n",
" optimizer.minimize(loss)\n", " opt.minimize(loss)\n",
" myLayer.clear_gradients()\n", " opt.clear_grad()\n",
" \n", "\n",
" # Record the learning process\n", " # Record the learning process\n",
" loss_list.append(loss.numpy()[0])\n", " loss_list.append(loss.numpy()[0])\n",
" parameter_list.append(myLayer.parameters()[0].numpy())\n", " parameter_list.append(myLayer.parameters()[0].numpy())\n",
" \n", "\n",
" print('The minimum value of the loss function is:', loss_list[-1])" "print('The minimum value of the loss function is:', loss_list[-1])"
] ]
}, },
{ {
...@@ -1106,11 +1075,11 @@ ...@@ -1106,11 +1075,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": 13,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:04:24.823063Z", "end_time": "2021-03-09T03:56:04.176637Z",
"start_time": "2021-01-09T13:04:24.807113Z" "start_time": "2021-03-09T03:56:03.680838Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -1119,8 +1088,8 @@ ...@@ -1119,8 +1088,8 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"The randomly generated matrix H according to the spectral decomposition is:\n", "The randomly generated matrix H according to the spectral decomposition is:\n",
"[[0.30704576+0.j 0.06071073-0.22154654j]\n", "[[ 0.26680964+0.j -0.06472222-0.17729436j]\n",
" [0.06071073+0.22154654j 0.69295424+0.j ]] \n", " [-0.06472222+0.17729436j 0.73319036+0.j ]] \n",
"\n", "\n",
"The eigenvalues of H are:\n", "The eigenvalues of H are:\n",
"[0.2 0.8]\n" "[0.2 0.8]\n"
...@@ -1150,11 +1119,11 @@ ...@@ -1150,11 +1119,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 16, "execution_count": 14,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:05:28.870563Z", "end_time": "2021-03-09T03:56:04.205868Z",
"start_time": "2021-01-09T13:05:28.864497Z" "start_time": "2021-03-09T03:56:04.186818Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -1162,10 +1131,10 @@ ...@@ -1162,10 +1131,10 @@
"# Hyper parameter settings\n", "# Hyper parameter settings\n",
"theta_size = 3 # set theta dimension\n", "theta_size = 3 # set theta dimension\n",
"num_qubits = 1 # Set the number of qubits\n", "num_qubits = 1 # Set the number of qubits\n",
"ITR = 10 # Set the number of iterations\n", "ITR = 50 # Set the number of iterations\n",
"LR = 0.2 # Set the learning rate\n", "LR = 0.5 # Set the learning rate\n",
"SEED = 1 # Fix random seed for initializing theta parameter\n", "SEED = 1 # Fix random seed for initializing theta parameter\n",
"\n", "paddle.seed(SEED)\n",
"\n", "\n",
"# Set the circuit module separately\n", "# Set the circuit module separately\n",
"def U_theta(theta):\n", "def U_theta(theta):\n",
...@@ -1182,25 +1151,26 @@ ...@@ -1182,25 +1151,26 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 17, "execution_count": 15,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:05:29.349729Z", "end_time": "2021-03-09T03:56:04.793520Z",
"start_time": "2021-01-09T13:05:29.340787Z" "start_time": "2021-03-09T03:56:04.781463Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Optimization_ex2(fluid.dygraph.Layer):\n", "class Optimization_ex2(paddle.nn.Layer):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " \n",
" low=0., high=2*np.pi, seed=SEED), dtype='float64'):\n", " def __init__(self, shape, dtype='float64'):\n",
" super(Optimization_ex2, self).__init__()\n", " super(Optimization_ex2, self).__init__()\n",
" \n", " \n",
" # Initialize a list of trainable parameters with length theta_size\n", " # Initialize a list of trainable parameters with length theta_size\n",
" # And use the uniform distribution of [0, 2*pi] to fill the initial value\n", " # And use the uniform distribution of [0, 2*pi] to fill the initial value\n",
" self.theta = self.create_parameter(\n", " self.theta = self.create_parameter(shape=shape, \n",
" shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0., high=2*np.pi), \n",
" self.H = fluid.dygraph.to_variable(H)\n", " dtype=dtype, is_bias=False)\n",
" self.H = paddle.to_tensor(H)\n",
" \n", " \n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -1212,18 +1182,18 @@ ...@@ -1212,18 +1182,18 @@
" U_dagger = dagger(U)\n", " U_dagger = dagger(U)\n",
" \n", " \n",
" # Calculate the loss function\n", " # Calculate the loss function\n",
" loss = matmul(U_dagger, matmul(self.H, U)).real[0][0]\n", " loss = paddle.real(matmul(U_dagger, matmul(self.H, U)))[0][0]\n",
" \n", " \n",
" return loss" " return loss"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 18, "execution_count": 16,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:05:30.086892Z", "end_time": "2021-03-09T03:56:11.561432Z",
"start_time": "2021-01-09T13:05:29.956476Z" "start_time": "2021-03-09T03:56:10.716719Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -1231,17 +1201,17 @@ ...@@ -1231,17 +1201,17 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 0 loss: 0.2064\n", "iter: 0 loss: 0.6071\n",
"iter: 1 loss: 0.2007\n", "iter: 5 loss: 0.4024\n",
"iter: 2 loss: 0.2033\n", "iter: 10 loss: 0.2953\n",
"iter: 3 loss: 0.2028\n", "iter: 15 loss: 0.2710\n",
"iter: 4 loss: 0.2013\n", "iter: 20 loss: 0.2666\n",
"iter: 5 loss: 0.2004\n", "iter: 25 loss: 0.2654\n",
"iter: 6 loss: 0.2008\n", "iter: 30 loss: 0.2643\n",
"iter: 7 loss: 0.2015\n", "iter: 35 loss: 0.2627\n",
"iter: 8 loss: 0.2016\n", "iter: 40 loss: 0.2601\n",
"iter: 9 loss: 0.2009\n", "iter: 45 loss: 0.2563\n",
"The minimum value of the loss function is: 0.20090539960637277\n" "The minimum value of the loss function is: 0.25196530073166423\n"
] ]
} }
], ],
...@@ -1249,33 +1219,29 @@ ...@@ -1249,33 +1219,29 @@
"loss_list = []\n", "loss_list = []\n",
"parameter_list = []\n", "parameter_list = []\n",
"\n", "\n",
"# Initialize paddle dynamic graph mechanism\n", "myLayer = Optimization_ex2([theta_size])\n",
"with fluid.dygraph.guard():\n", "\n",
" \n", "# SGD optimizer\n",
" myLayer = Optimization_ex2([theta_size])\n", "opt = paddle.optimizer.SGD(learning_rate = LR, parameters = myLayer.parameters())\n",
" \n", "\n",
" # Generally speaking, we use Adam optimizer to get relatively good convergence\n", "# Optimization cycle\n",
" # Of course you can change to SGD or RMS prop.\n", "for itr in range(ITR):\n",
" optimizer = fluid.optimizer.AdamOptimizer(\n", "\n",
" learning_rate = LR, parameter_list = myLayer.parameters())\n", " # Forward propagation calculates loss function\n",
" \n", " loss = myLayer()[0]\n",
" # Optimization cycle\n", "\n",
" for itr in range(ITR):\n", " # Back propagation minimizes the loss function\n",
" \n", " loss.backward()\n",
" # Forward propagation calculates loss function\n", " opt.minimize(loss)\n",
" loss = myLayer()[0]\n", " opt.clear_grad()\n",
" \n", "\n",
" # Under the dynamic graph mechanism, back propagation minimizes the loss function\n", " # Record the learning curve\n",
" loss.backward()\n", " loss_list.append(loss.numpy()[0])\n",
" optimizer.minimize(loss)\n", " parameter_list.append(myLayer.parameters()[0].numpy())\n",
" myLayer.clear_gradients()\n", " if itr % 5 == 0:\n",
" \n",
" # Record the learning curve\n",
" loss_list.append(loss.numpy()[0])\n",
" parameter_list.append(myLayer.parameters()[0].numpy())\n",
" print('iter:', itr, 'loss: %.4f'% loss.numpy())\n", " print('iter:', itr, 'loss: %.4f'% loss.numpy())\n",
" \n", "\n",
" print('The minimum value of the loss function is:', loss_list[-1])" "print('The minimum value of the loss function is:', loss_list[-1])"
] ]
}, },
{ {
...@@ -1320,20 +1286,15 @@ ...@@ -1320,20 +1286,15 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 35, "execution_count": 17,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:08:40.727331Z", "end_time": "2021-03-09T03:56:15.148775Z",
"start_time": "2021-01-09T13:08:40.721736Z" "start_time": "2021-03-09T03:56:15.092238Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n",
"from paddle import fluid\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import pauli_str_to_matrix\n",
"\n",
"# First generate the Hamiltonian under Pauli string representation\n", "# First generate the Hamiltonian under Pauli string representation\n",
"# H_info is equivalent to 0.4*kron(I, Z) + 0.4*kron(Z, I) + 0.2*kron(X, X)\n", "# H_info is equivalent to 0.4*kron(I, Z) + 0.4*kron(Z, I) + 0.2*kron(X, X)\n",
"# Among them, X, Y, Z are the Pauli matrix and I is the identity matrix\n", "# Among them, X, Y, Z are the Pauli matrix and I is the identity matrix\n",
...@@ -1342,9 +1303,10 @@ ...@@ -1342,9 +1303,10 @@
"# Set hyper parameter\n", "# Set hyper parameter\n",
"num_qubits = 2\n", "num_qubits = 2\n",
"theta_size = 4\n", "theta_size = 4\n",
"ITR = 10\n", "ITR = 60\n",
"LR = 0.6\n", "LR = 0.4\n",
"SEED = 1\n", "SEED = 999\n",
"paddle.seed(SEED)\n",
"\n", "\n",
"# Convert the Hamiltonian into matrix representation\n", "# Convert the Hamiltonian into matrix representation\n",
"H_matrix = pauli_str_to_matrix(H_info, num_qubits)" "H_matrix = pauli_str_to_matrix(H_info, num_qubits)"
...@@ -1352,24 +1314,25 @@ ...@@ -1352,24 +1314,25 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 36, "execution_count": 18,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:08:41.137003Z", "end_time": "2021-03-09T03:56:15.789743Z",
"start_time": "2021-01-09T13:08:41.125057Z" "start_time": "2021-03-09T03:56:15.776313Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class vqe_demo(fluid.dygraph.Layer):\n", "class vqe_demo(paddle.nn.Layer):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " \n",
" low=0., high=2*np.pi, seed=SEED), dtype='float64'):\n", " def __init__(self, shape, dtype='float64'):\n",
" super(vqe_demo, self).__init__()\n", " super(vqe_demo, self).__init__()\n",
" \n", " \n",
" # Initialize a list of learnable parameters with length theta_size\n", " # Initialize a list of learnable parameters with length theta_size\n",
" # Use the uniform distribution of [0, 2*pi] to fill the initial value\n", " # Use the uniform distribution of [0, 2*pi] to fill the initial value\n",
" self.theta = self.create_parameter(\n", " self.theta = self.create_parameter(shape=shape, \n",
" shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0., high=2*np.pi), \n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -1396,11 +1359,11 @@ ...@@ -1396,11 +1359,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 37, "execution_count": 19,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T13:08:44.573571Z", "end_time": "2021-03-09T03:56:27.823274Z",
"start_time": "2021-01-09T13:08:41.546193Z" "start_time": "2021-03-09T03:56:20.363130Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -1408,17 +1371,13 @@ ...@@ -1408,17 +1371,13 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 0 loss: 0.3195\n", "iter: 0 loss: -0.2202\n",
"iter: 1 loss: -0.4650\n", "iter: 10 loss: -0.7239\n",
"iter: 2 loss: -0.7123\n", "iter: 20 loss: -0.8156\n",
"iter: 3 loss: -0.7690\n", "iter: 30 loss: -0.8172\n",
"iter: 4 loss: -0.7925\n", "iter: 40 loss: -0.8205\n",
"iter: 5 loss: -0.8096\n", "iter: 50 loss: -0.8241\n",
"iter: 6 loss: -0.8186\n", "The calculated ground state energy is: -0.8243637430772154\n",
"iter: 7 loss: -0.8225\n",
"iter: 8 loss: -0.8239\n",
"iter: 9 loss: -0.8244\n",
"The calculated ground state energy is: -0.8243582047336566\n",
"The real ground state energy is: -0.8246211251235321\n" "The real ground state energy is: -0.8246211251235321\n"
] ]
} }
...@@ -1427,36 +1386,34 @@ ...@@ -1427,36 +1386,34 @@
"loss_list = []\n", "loss_list = []\n",
"parameter_list = []\n", "parameter_list = []\n",
"\n", "\n",
"# Initialize paddle dynamic computational graph\n", "# Define network dimensions\n",
"with fluid.dygraph.guard():\n", "vqe = vqe_demo([theta_size])\n",
" \n", "\n",
" # Define network dimensions\n", "# We usually use Adam optimizer to get relatively good convergence\n",
" vqe = vqe_demo([theta_size])\n", "# Of course you can change it to SGD, Adagrad, or RMS prop as we did here.\n",
" \n", "opt = paddle.optimizer.Adam(\n",
" # We usually use Adam optimizer to get relatively good convergence\n", " learning_rate = LR, parameters = vqe.parameters())\n",
" # Of course you can change it to SGD, Adagrad, or RMS prop as we did here.\n", "\n",
" optimizer = fluid.optimizer.AdagradOptimizer(\n", "# Optimization cycle\n",
" learning_rate = LR, parameter_list = vqe.parameters())\n", "for itr in range(ITR):\n",
" \n", "\n",
" # Optimization cycle\n", " # Forward propagation calculates loss function\n",
" for itr in range(ITR):\n", " loss = vqe()\n",
" \n", "\n",
" # Forward propagation calculates loss function\n", " # Back propagation minimizes the loss function\n",
" loss = vqe()\n", " loss.backward()\n",
" \n", " opt.minimize(loss)\n",
" # Under the dynamic graph mechanism, back propagation minimizes the loss function\n", " opt.clear_grad()\n",
" loss.backward()\n", "\n",
" optimizer.minimize(loss)\n", " # Record the learning curve\n",
" vqe.clear_gradients()\n", " loss_list.append(loss.numpy()[0])\n",
" \n", " parameter_list.append(vqe.parameters()[0].numpy())\n",
" # Record the learning curve\n", " if itr % 10 == 0:\n",
" loss_list.append(loss.numpy()[0])\n",
" parameter_list.append(vqe.parameters()[0].numpy())\n",
" print('iter:', itr, 'loss: %.4f'% loss.numpy())\n", " print('iter:', itr, 'loss: %.4f'% loss.numpy())\n",
" \n", "\n",
" \n", "\n",
" print('The calculated ground state energy is:', loss_list[-1])\n", "print('The calculated ground state energy is:', loss_list[-1])\n",
" print('The real ground state energy is:', np.linalg.eigh(H_matrix)[0][0])" "print('The real ground state energy is:', np.linalg.eigh(H_matrix)[0][0])"
] ]
}, },
{ {
...@@ -1503,7 +1460,7 @@ ...@@ -1503,7 +1460,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.0"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
...@@ -1514,9 +1471,43 @@ ...@@ -1514,9 +1471,43 @@
"title_cell": "Table of Contents", "title_cell": "Table of Contents",
"title_sidebar": "Contents", "title_sidebar": "Contents",
"toc_cell": false, "toc_cell": false,
"toc_position": {}, "toc_position": {
"height": "calc(100% - 180px)",
"left": "10px",
"top": "150px",
"width": "580px"
},
"toc_section_display": true, "toc_section_display": true,
"toc_window_display": true "toc_window_display": true
},
"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
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -42,4 +42,4 @@ def H_generator(): ...@@ -42,4 +42,4 @@ def H_generator():
# Convert to the data type supported by Paddle Quantum # Convert to the data type supported by Paddle Quantum
hamiltonian = hamiltonian.astype("complex128") hamiltonian = hamiltonian.astype("complex128")
rho_G = rho_G.astype("complex128") rho_G = rho_G.astype("complex128")
return hamiltonian, rho_G return hamiltonian, rho_G
\ No newline at end of file
...@@ -16,12 +16,10 @@ ...@@ -16,12 +16,10 @@
Paddle_GIBBS Paddle_GIBBS
""" """
import scipy
from numpy import pi as PI from numpy import pi as PI
from paddle import fluid import paddle
from paddle.complex import matmul, trace from paddle import matmul, trace
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
from paddle_quantum.state import density_op from paddle_quantum.state import density_op
from paddle_quantum.utils import state_fidelity, partial_trace from paddle_quantum.utils import state_fidelity, partial_trace
...@@ -51,38 +49,38 @@ def U_theta(initial_state, theta, N, D): ...@@ -51,38 +49,38 @@ def U_theta(initial_state, theta, N, D):
for i in range(N): for i in range(N):
cir.ry(theta=theta[D][i][0], which_qubit=i) cir.ry(theta=theta[D][i][0], which_qubit=i)
# Act quantum neural network on initilized state # Act quantum neural network on initialized state
final_state = cir.run_density_matrix(initial_state) final_state = cir.run_density_matrix(initial_state)
return final_state return final_state
class Net(fluid.dygraph.Layer): class Net(paddle.nn.Layer):
""" """
Construct the model net Construct the model net
""" """
def __init__(self, N, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * PI, seed=SEED), def __init__(self, N, shape, param_attr=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI),
dtype='float64'): dtype='float64'):
super(Net, self).__init__() super(Net, self).__init__()
# Initialize theta by sampling from a uniform distribution [0, 2*pi] # Initialize theta by sampling from a uniform distribution [0, 2*pi]
self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False) self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
# Set the initial state as rho = |0..0><0..0| # Set the initial state as rho = |0..0><0..0|
self.initial_state = fluid.dygraph.to_variable(density_op(N)) self.initial_state = paddle.to_tensor(density_op(N))
# Define the loss function and forward propagation mechanism # Define the loss function and forward propagation mechanism
def forward(self, H, N, N_SYS_B, beta, D): def forward(self, H, N, N_SYS_B, beta, D):
# Apply quantum neural network onto the initial state # Apply quantum neural network onto the initial state
rho_AB = U_theta(self.initial_state, self.theta, N, D) rho_AB = U_theta(self.initial_state, self.theta, N, D)
# Calculate the partial tarce to get the state rho_B of subsystem B # Calculate the partial trace to get the state rho_B of subsystem B
rho_B = partial_trace(rho_AB, 2 ** (N - N_SYS_B), 2 ** (N_SYS_B), 1) rho_B = partial_trace(rho_AB, 2 ** (N - N_SYS_B), 2 ** N_SYS_B, 1)
# Calculate the three components of the loss function # Calculate the three components of the loss function
rho_B_squre = matmul(rho_B, rho_B) rho_B_squre = matmul(rho_B, rho_B)
loss1 = (trace(matmul(rho_B, H))).real loss1 = paddle.real(trace(matmul(rho_B, H)))
loss2 = (trace(rho_B_squre)).real * 2 / beta loss2 = paddle.real(trace(rho_B_squre)) * 2 / beta
loss3 = - ((trace(matmul(rho_B_squre, rho_B))).real + 3) / (2 * beta) loss3 = - (paddle.real(trace(matmul(rho_B_squre, rho_B))) + 3) / (2 * beta)
# Get the final loss function # Get the final loss function
loss = loss1 + loss2 + loss3 loss = loss1 + loss2 + loss3
...@@ -90,7 +88,7 @@ class Net(fluid.dygraph.Layer): ...@@ -90,7 +88,7 @@ class Net(fluid.dygraph.Layer):
return loss, rho_B return loss, rho_B
def Paddle_GIBBS(hamiltonian, rho_G, N=4, N_SYS_B=3, beta=1.5, D=1, ITR=50, LR=0.5): def Paddle_GIBBS(hamiltonian, rho_G, N=4, N_SYS_B=3, beta=1.5, D=1, ITR=50, LR=0.2):
r""" r"""
Paddle_GIBBS Paddle_GIBBS
:param hamiltonian: Hamiltonian :param hamiltonian: Hamiltonian
...@@ -102,36 +100,35 @@ def Paddle_GIBBS(hamiltonian, rho_G, N=4, N_SYS_B=3, beta=1.5, D=1, ITR=50, LR=0 ...@@ -102,36 +100,35 @@ def Paddle_GIBBS(hamiltonian, rho_G, N=4, N_SYS_B=3, beta=1.5, D=1, ITR=50, LR=0
:param LR: Learning rate :param LR: Learning rate
:return: State prepared by optimized QNN :return: State prepared by optimized QNN
""" """
# Initialize PaddlePaddle dynamic graph machanism # We need to convert Numpy array to variable supported in PaddlePaddle
with fluid.dygraph.guard(): H = paddle.to_tensor(hamiltonian)
# We need to convert Numpy array to variable supported in PaddlePaddle
H = fluid.dygraph.to_variable(hamiltonian) # Fix the dimensions of network
net = Net(N, shape=[D + 1, N, 1])
# Fix the dimensions of network
net = Net(N, shape=[D + 1, N, 1]) # Usually, we recommend Adam optimizer for better results. If you wish, you could use SGD or RMS prop.
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
# Usually, we recommend Adam optimizer for better results. If you wish, you could use SGD or RMS prop.
opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters()) # Optimization iterations
for itr in range(1, ITR + 1):
# Optimization iterations # Run forward propagation to calculate loss function and obtain state rho_B
for itr in range(1, ITR + 1): loss, rho_B = net(H, N, N_SYS_B, beta, D)
# Run forward propagation to calculate loss function and obtain state rho_B
loss, rho_B = net(H, N, N_SYS_B, beta, D) # In dynamic graph, run backward propagation to minimize loss function
loss.backward()
# In dynamic graph, run backward propogation to minimize loss function opt.minimize(loss)
loss.backward() opt.clear_grad()
opt.minimize(loss) # Convert variable to Numpy array to calculate fidelity F(rho_B, rho_G)
net.clear_gradients() rho_B = rho_B.numpy()
# Convert variable to Numpy array to calculate fidelity F(rho_B, rho_G) fid = state_fidelity(rho_B, rho_G)
rho_B = rho_B.numpy() # Print results
fid = state_fidelity(rho_B, rho_G) if itr % 5 == 0:
# Print results print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:', '%.4f' % fid)
if itr % 5 == 0:
print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:', '%.4f' % fid)
return rho_B return rho_B
def main(): def main():
paddle.seed(SEED)
# Generate gibbs Hamiltonian # Generate gibbs Hamiltonian
hamiltonian, rho_G = H_generator() hamiltonian, rho_G = H_generator()
rho_B = Paddle_GIBBS(hamiltonian, rho_G) rho_B = Paddle_GIBBS(hamiltonian, rho_G)
......
...@@ -17,6 +17,7 @@ main ...@@ -17,6 +17,7 @@ main
""" """
import scipy import scipy
import paddle
from numpy import trace as np_trace from numpy import trace as np_trace
from paddle_quantum.utils import pauli_str_to_matrix from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.GIBBS.Paddle_GIBBS import Paddle_GIBBS from paddle_quantum.GIBBS.Paddle_GIBBS import Paddle_GIBBS
......
...@@ -17,13 +17,12 @@ Paddle_QAOA: To learn more about the functions and properties of this applicatio ...@@ -17,13 +17,12 @@ Paddle_QAOA: To learn more about the functions and properties of this applicatio
you could check the corresponding Jupyter notebook under the Tutorial folder. you could check the corresponding Jupyter notebook under the Tutorial folder.
""" """
from paddle import fluid
import os import os
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import networkx as nx import networkx as nx
import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import pauli_str_to_matrix from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator
...@@ -114,7 +113,7 @@ def circuit_extend_QAOA(theta, adjacency_matrix, N, P): ...@@ -114,7 +113,7 @@ def circuit_extend_QAOA(theta, adjacency_matrix, N, P):
return cir return cir
class Net(fluid.dygraph.Layer): class Net(paddle.nn.Layer):
""" """
It constructs the net for QAOA which combines the QAOA circuit with the classical optimizer which sets rules It constructs the net for QAOA which combines the QAOA circuit with the classical optimizer which sets rules
to update parameters described by theta introduced in the QAOA circuit. to update parameters described by theta introduced in the QAOA circuit.
...@@ -124,7 +123,7 @@ class Net(fluid.dygraph.Layer): ...@@ -124,7 +123,7 @@ class Net(fluid.dygraph.Layer):
def __init__( def __init__(
self, self,
shape, shape,
param_attr=fluid.initializer.Uniform(low=0.0, high=np.pi, seed=SEED), param_attr=paddle.nn.initializer.Uniform(low=0.0, high=np.pi),
dtype="float64", dtype="float64",
): ):
super(Net, self).__init__() super(Net, self).__init__()
...@@ -179,36 +178,35 @@ def Paddle_QAOA(classical_graph_adjacency, N, P, METHOD, ITR, LR): ...@@ -179,36 +178,35 @@ def Paddle_QAOA(classical_graph_adjacency, N, P, METHOD, ITR, LR):
Returns: Returns:
the optimized QAOA circuit the optimized QAOA circuit
""" """
with fluid.dygraph.guard(): # Construct the net or QAOA circuits based on the standard modules
# Construct the net or QAOA circuits based on the standard modules if METHOD == 1:
if METHOD == 1: net = Net(shape=[P, 2])
net = Net(shape=[P, 2]) # Construct the net or QAOA circuits based on the extended modules
# Construct the net or QAOA circuits based on the extended modules elif METHOD == 2:
elif METHOD == 2: net = Net(shape=[P, 4])
net = Net(shape=[P, 4]) else:
else: raise ValueError("Wrong method called!")
raise ValueError("Wrong method called!")
# Classical optimizer
# Classical optimizer opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())
# Gradient descent loop
# Gradient descent loop summary_iter, summary_loss = [], []
summary_iter, summary_loss = [], [] for itr in range(1, ITR + 1):
for itr in range(1, ITR + 1): loss, cir = net(
loss, cir = net( classical_graph_adjacency, N, P, METHOD
classical_graph_adjacency, N, P, METHOD )
) loss.backward()
loss.backward() opt.minimize(loss)
opt.minimize(loss) opt.clear_grad()
net.clear_gradients()
if itr % 10 == 0: if itr % 10 == 0:
print("iter:", itr, " loss:", "%.4f" % loss.numpy()) print("iter:", itr, " loss:", "%.4f" % loss.numpy())
summary_loss.append(loss[0][0].numpy()) summary_loss.append(loss[0][0].numpy())
summary_iter.append(itr) summary_iter.append(itr)
theta_opt = net.parameters()[0].numpy() theta_opt = net.parameters()[0].numpy()
print("Optmized parameters theta:\n", theta_opt) # print("Optimized parameters theta:\n", theta_opt)
os.makedirs("output", exist_ok=True) os.makedirs("output", exist_ok=True)
np.savez("./output/summary_data", iter=summary_iter, energy=summary_loss) np.savez("./output/summary_data", iter=summary_iter, energy=summary_loss)
...@@ -217,6 +215,7 @@ def Paddle_QAOA(classical_graph_adjacency, N, P, METHOD, ITR, LR): ...@@ -217,6 +215,7 @@ def Paddle_QAOA(classical_graph_adjacency, N, P, METHOD, ITR, LR):
def main(N=4): def main(N=4):
paddle.seed(SEED)
# number of qubits or number of nodes in the graph # number of qubits or number of nodes in the graph
N = 4 N = 4
classical_graph, classical_graph_adjacency = generate_graph(N, GRAPHMETHOD=1) classical_graph, classical_graph_adjacency = generate_graph(N, GRAPHMETHOD=1)
...@@ -264,9 +263,8 @@ def main(N=4): ...@@ -264,9 +263,8 @@ def main(N=4):
# Show the plot # Show the plot
plt.show() plt.show()
with fluid.dygraph.guard(): # Measure the output state of the QAOA circuit for 1024 shots by default
# Measure the output state of the QAOA circuit for 1024 shots by default prob_measure = opt_cir.measure(plot=True)
prob_measure = opt_cir.measure(plot=True)
# Find the max value in measured probability of bitstrings # Find the max value in measured probability of bitstrings
max_prob = max(prob_measure.values()) max_prob = max(prob_measure.values())
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
""" """
Benchmark Benchmark
""" """
from matplotlib import pyplot from matplotlib import pyplot
from numpy import diag, max, min, load, ones from numpy import diag, max, min, load, ones
from paddle_quantum.utils import pauli_str_to_matrix from paddle_quantum.utils import pauli_str_to_matrix
...@@ -48,8 +49,8 @@ def benchmark_QAOA(classical_graph_adjacency=None, N=None): ...@@ -48,8 +49,8 @@ def benchmark_QAOA(classical_graph_adjacency=None, N=None):
# Plot it # Plot it
pyplot.figure(1) pyplot.figure(1)
loss_QAOA, = pyplot.plot(x1['iter'], x1['energy'], \ loss_QAOA, = pyplot.plot(x1['iter'], x1['energy'],
alpha=0.7, marker='', linestyle="--", linewidth=2, color='m') alpha=0.7, marker='', linestyle="--", linewidth=2, color='m')
benchmark, = pyplot.plot( benchmark, = pyplot.plot(
x1['iter'], x1['iter'],
H_min, H_min,
...@@ -78,7 +79,6 @@ def main(): ...@@ -78,7 +79,6 @@ def main():
""" """
main main
""" """
benchmark_QAOA() benchmark_QAOA()
......
...@@ -16,13 +16,11 @@ ...@@ -16,13 +16,11 @@
main main
""" """
from paddle import fluid
import os
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import networkx as nx import networkx as nx
import paddle
from paddle_quantum.utils import pauli_str_to_matrix from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.QAOA.Paddle_QAOA import Paddle_QAOA from paddle_quantum.QAOA.Paddle_QAOA import Paddle_QAOA
from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator
...@@ -76,9 +74,8 @@ def main(N=4): ...@@ -76,9 +74,8 @@ def main(N=4):
# Show the plot # Show the plot
plt.show() plt.show()
with fluid.dygraph.guard(): # Measure the output state of the QAOA circuit for 1024 shots by default
# Measure the output state of the QAOA circuit for 1024 shots by default prob_measure = opt_cir.measure(plot=True)
prob_measure = opt_cir.measure(plot=True)
# Find the max value in measured probability of bitstrings # Find the max value in measured probability of bitstrings
max_prob = max(prob_measure.values()) max_prob = max(prob_measure.values())
......
...@@ -30,6 +30,6 @@ def H_generator(N): ...@@ -30,6 +30,6 @@ def H_generator(N):
hamiltonian = random_pauli_str_generator(N, terms=10) hamiltonian = random_pauli_str_generator(N, terms=10)
print("Random Hamiltonian in Pauli string format = \n", hamiltonian) print("Random Hamiltonian in Pauli string format = \n", hamiltonian)
# Generate the marix form of the Hamiltonian # Generate the matrix form of the Hamiltonian
H = pauli_str_to_matrix(hamiltonian, N) H = pauli_str_to_matrix(hamiltonian, N)
return H return H
...@@ -19,8 +19,8 @@ you could check the corresponding Jupyter notebook under the Tutorial folder. ...@@ -19,8 +19,8 @@ you could check the corresponding Jupyter notebook under the Tutorial folder.
import numpy import numpy
from paddle.complex import matmul import paddle
from paddle import fluid from paddle import matmul
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import dagger from paddle_quantum.utils import dagger
from paddle_quantum.SSVQE.HGenerator import H_generator from paddle_quantum.SSVQE.HGenerator import H_generator
...@@ -43,18 +43,18 @@ def U_theta(theta, N): ...@@ -43,18 +43,18 @@ def U_theta(theta, N):
cir = UAnsatz(N) cir = UAnsatz(N)
# Use a built-in QNN template # Use a built-in QNN template
cir.universal_2_qubit_gate(theta) cir.universal_2_qubit_gate(theta, [0, 1])
# Return the Unitary matrix simulated by QNN # Return the Unitary matrix simulated by QNN
return cir.U return cir.U
class Net(fluid.dygraph.Layer): class Net(paddle.nn.Layer):
""" """
Construct the model net Construct the model net
""" """
def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * numpy.pi, seed=SEED), def __init__(self, shape, param_attr=paddle.nn.initializer.Uniform(low=0.0, high=2 * numpy.pi),
dtype='float64'): dtype='float64'):
super(Net, self).__init__() super(Net, self).__init__()
...@@ -67,7 +67,7 @@ class Net(fluid.dygraph.Layer): ...@@ -67,7 +67,7 @@ class Net(fluid.dygraph.Layer):
U = U_theta(self.theta, N) U = U_theta(self.theta, N)
# Calculate loss function # Calculate loss function
loss_struct = matmul(matmul(dagger(U), H), U).real loss_struct = paddle.real(matmul(matmul(dagger(U), H), U))
# Use computational basis to calculate each expectation value, which is the same # Use computational basis to calculate each expectation value, which is the same
# as a diagonal element in U^dagger*H*U # as a diagonal element in U^dagger*H*U
...@@ -94,36 +94,35 @@ def Paddle_SSVQE(H, N=2, THETA_SIZE=15, ITR=50, LR=0.3): ...@@ -94,36 +94,35 @@ def Paddle_SSVQE(H, N=2, THETA_SIZE=15, ITR=50, LR=0.3):
:param LR: Learning rate :param LR: Learning rate
:return: First several smallest eigenvalues of the Hamiltonian :return: First several smallest eigenvalues of the Hamiltonian
""" """
# Initialize PaddlePaddle dynamic graph machanism # We need to convert Numpy array to variable supported in PaddlePaddle
with fluid.dygraph.guard(): hamiltonian = paddle.to_tensor(H)
# We need to convert Numpy array to variable supported in PaddlePaddle
hamiltonian = fluid.dygraph.to_variable(H) # Fix the dimensions of network
net = Net(shape=[THETA_SIZE])
# Fix the dimensions of network
net = Net(shape=[THETA_SIZE]) # Use Adagrad optimizer
opt = paddle.optimizer.Adagrad(learning_rate=LR, parameters=net.parameters())
# Use Adagrad optimizer
opt = fluid.optimizer.AdagradOptimizer(learning_rate=LR, parameter_list=net.parameters()) # Optimization iterations
for itr in range(1, ITR + 1):
# Optimization iterations
for itr in range(1, ITR + 1): # Run forward propagation to calculate loss function and obtain energy spectrum
loss, loss_components = net(hamiltonian, N)
# Run forward propagation to calculate loss function and obtain energy spectrum
loss, loss_components = net(hamiltonian, N) # In dynamic graph, run backward propagation to minimize loss function
loss.backward()
# In dynamic graph, run backward propogation to minimize loss function opt.minimize(loss)
loss.backward() opt.clear_grad()
opt.minimize(loss)
net.clear_gradients() # Print results
if itr % 10 == 0:
# Print results print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])
if itr % 10 == 0:
print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])
return loss_components return loss_components
def main(): def main():
paddle.seed(SEED)
N = 2 N = 2
H = H_generator(N) H = H_generator(N)
......
...@@ -17,6 +17,7 @@ main ...@@ -17,6 +17,7 @@ main
""" """
import numpy import numpy
import paddle
from paddle_quantum.SSVQE.HGenerator import H_generator from paddle_quantum.SSVQE.HGenerator import H_generator
from paddle_quantum.SSVQE.Paddle_SSVQE import Paddle_SSVQE from paddle_quantum.SSVQE.Paddle_SSVQE import Paddle_SSVQE
......
...@@ -20,9 +20,9 @@ you could check the corresponding Jupyter notebook under the Tutorial folder. ...@@ -20,9 +20,9 @@ you could check the corresponding Jupyter notebook under the Tutorial folder.
import os import os
import platform import platform
import paddle
from numpy import pi as PI from numpy import pi as PI
from numpy import savez from numpy import savez
from paddle import fluid
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
from paddle_quantum.VQE.benchmark import benchmark_result from paddle_quantum.VQE.benchmark import benchmark_result
from paddle_quantum.VQE.chemistrysub import H2_generator from paddle_quantum.VQE.chemistrysub import H2_generator
...@@ -58,12 +58,12 @@ def U_theta(theta, Hamiltonian, N, D): ...@@ -58,12 +58,12 @@ def U_theta(theta, Hamiltonian, N, D):
return expectation_val return expectation_val
class StateNet(fluid.dygraph.Layer): class StateNet(paddle.nn.Layer):
""" """
Construct the model net Construct the model net
""" """
def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * PI), dtype="float64"): def __init__(self, shape, param_attr=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI), dtype="float64"):
super(StateNet, self).__init__() super(StateNet, self).__init__()
# Initialize theta by sampling from a uniform distribution [0, 2*pi] # Initialize theta by sampling from a uniform distribution [0, 2*pi]
...@@ -88,41 +88,38 @@ def Paddle_VQE(Hamiltonian, N, D=2, ITR=80, LR=0.2): ...@@ -88,41 +88,38 @@ def Paddle_VQE(Hamiltonian, N, D=2, ITR=80, LR=0.2):
:return: No return :return: No return
""" """
# Initialize PaddlePaddle dynamic graph machanism # Determine the dimensions of network
with fluid.dygraph.guard(): net = StateNet(shape=[D + 1, N, 1])
# Determine the dimensions of network
# 确定网络的参数维度 # Usually, we recommend Adam optimizer for better result. If you wish, you could use SGD or RMS prop.
net = StateNet(shape=[D + 1, N, 1]) opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
# Usually, we recommend Adam optimizer for better result. If you wish, you could use SGD or RMS prop. # Record optimization results
opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters()) summary_iter, summary_loss = [], []
# Record optimization results # Optimization iterations
summary_iter, summary_loss = [], [] for itr in range(1, ITR + 1):
# Optimization iterations # Run forward propagation to calculate loss function
for itr in range(1, ITR + 1): loss = net(Hamiltonian, N, D)
# Run forward propagation to calculate loss function # In dynamic graph, run backward propagation to minimize loss function
loss = net(Hamiltonian, N, D) loss.backward()
opt.minimize(loss)
# In dynamic graph, run backward propogation to minimize loss function opt.clear_grad()
loss.backward()
opt.minimize(loss) # Update optimized results
net.clear_gradients() summary_loss.append(loss.numpy())
summary_iter.append(itr)
# Update optimized results
summary_loss.append(loss.numpy()) # Print results
summary_iter.append(itr) if itr % 20 == 0:
print("iter:", itr, "loss:", "%.4f" % loss.numpy())
# Print results print("iter:", itr, "Ground state energy:", "%.4f Ha" % loss.numpy())
if itr % 20 == 0:
print("iter:", itr, "loss:", "%.4f" % loss.numpy()) # Save results in the 'output' directory
print("iter:", itr, "Ground state energy:", "%.4f Ha" % loss.numpy()) os.makedirs("output", exist_ok=True)
savez("./output/summary_data", iter=summary_iter, energy=summary_loss)
# Save results in the 'output' directory
os.makedirs("output", exist_ok=True)
savez("./output/summary_data", iter=summary_iter, energy=summary_loss)
def main(): def main():
......
...@@ -40,7 +40,7 @@ def benchmark_result(): ...@@ -40,7 +40,7 @@ def benchmark_result():
elif sysStr == 'Linux' or sysStr == 'Darwin': elif sysStr == 'Linux' or sysStr == 'Darwin':
# for linux only # for linux only
from paddle_quantum.VQE.chemistrygen import read_calc_H from paddle_quantum.VQE.chemistrygen import read_calc_H
# Harmiltonian and cnot module preparing, must be executed under Linux # Hamiltonian and cnot module preparing, must be executed under Linux
# Read the H2 molecule data # Read the H2 molecule data
print('Molecule data will be read from h2.xyz') print('Molecule data will be read from h2.xyz')
Hamiltonian, N = read_calc_H(geo_fn='h2.xyz') Hamiltonian, N = read_calc_H(geo_fn='h2.xyz')
......
...@@ -113,20 +113,12 @@ def read_calc_H(geo_fn, multiplicity=1, charge=0): ...@@ -113,20 +113,12 @@ def read_calc_H(geo_fn, multiplicity=1, charge=0):
geo.append([species, (float(x), float(y), float(z))]) geo.append([species, (float(x), float(y), float(z))])
# meanfield data # meanfield data
mol = openfermion.hamiltonians.MolecularData(geo, 'sto-3g', multiplicity, molecular_hamiltonian = openfermionpyscf.generate_molecular_hamiltonian(geo, 'sto-3g', multiplicity, charge)
charge) qubit_op = openfermion.transforms.jordan_wigner(molecular_hamiltonian)
openfermionpyscf.run_pyscf(mol)
terms_molecular_hamiltonian = mol.get_molecular_hamiltonian(
)
fermionic_hamiltonian = openfermion.transforms.get_fermion_operator(
terms_molecular_hamiltonian)
qubit_op = openfermion.transforms.jordan_wigner(
fermionic_hamiltonian)
# calc H # calc H
Hamiltonian = Hamiltonian_str_convert(qubit_op) Hamiltonian = Hamiltonian_str_convert(qubit_op)
return Hamiltonian, mol.n_qubits return Hamiltonian, molecular_hamiltonian.n_qubits
def main(): def main():
......
...@@ -18,6 +18,7 @@ main ...@@ -18,6 +18,7 @@ main
import platform import platform
import paddle
from paddle_quantum.VQE.Paddle_VQE import Paddle_VQE from paddle_quantum.VQE.Paddle_VQE import Paddle_VQE
from paddle_quantum.VQE.benchmark import benchmark_result from paddle_quantum.VQE.benchmark import benchmark_result
from paddle_quantum.VQE.chemistrysub import H2_generator from paddle_quantum.VQE.chemistrysub import H2_generator
......
...@@ -18,6 +18,7 @@ HGenerator ...@@ -18,6 +18,7 @@ HGenerator
from numpy import diag from numpy import diag
import scipy import scipy
import scipy.stats
SEED = 13 SEED = 13
......
...@@ -18,10 +18,10 @@ you could check the corresponding Jupyter notebook under the Tutorial folder. ...@@ -18,10 +18,10 @@ you could check the corresponding Jupyter notebook under the Tutorial folder.
""" """
import numpy import numpy
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import dagger from paddle_quantum.utils import dagger
from paddle.complex import matmul, trace from paddle import matmul, trace
from paddle_quantum.VQSD.HGenerator import generate_rho_sigma from paddle_quantum.VQSD.HGenerator import generate_rho_sigma
SEED = 14 SEED = 14
...@@ -42,23 +42,23 @@ def U_theta(theta, N): ...@@ -42,23 +42,23 @@ def U_theta(theta, N):
cir = UAnsatz(N) cir = UAnsatz(N)
# Use built-in template # Use built-in template
cir.universal_2_qubit_gate(theta) cir.universal_2_qubit_gate(theta, [0, 1])
# Return the Unitary matrix simulated by QNN # Return the Unitary matrix simulated by QNN
return cir.U return cir.U
class Net(fluid.dygraph.Layer): class Net(paddle.nn.Layer):
""" """
Construct the model net Construct the model net
""" """
def __init__(self, shape, rho, sigma, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * numpy.pi, seed=SEED), def __init__(self, shape, rho, sigma, param_attr=paddle.nn.initializer.Uniform(low=0.0, high=2 * numpy.pi),
dtype='float64'): dtype='float64'):
super(Net, self).__init__() super(Net, self).__init__()
# Convert Numpy array to variable supported in PaddlePaddle # Convert Numpy array to variable supported in PaddlePaddle
self.rho = fluid.dygraph.to_variable(rho) self.rho = paddle.to_tensor(rho)
self.sigma = fluid.dygraph.to_variable(sigma) self.sigma = paddle.to_tensor(sigma)
# Initialize theta by sampling from a uniform distribution [0, 2*pi] # Initialize theta by sampling from a uniform distribution [0, 2*pi]
self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False) self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
...@@ -74,10 +74,10 @@ class Net(fluid.dygraph.Layer): ...@@ -74,10 +74,10 @@ class Net(fluid.dygraph.Layer):
# Calculate loss function # Calculate loss function
loss = trace(matmul(self.sigma, rho_tilde)) loss = trace(matmul(self.sigma, rho_tilde))
return loss.real, rho_tilde return paddle.real(loss), rho_tilde
def Paddle_VQSD(rho, sigma, N=2, THETA_SIZE=15, ITR=50, LR=0.1): def Paddle_VQSD(rho, sigma, N=2, THETA_SIZE=15, ITR=50, LR=0.2):
r""" r"""
Paddle_VQSD Paddle_VQSD
:param rho: Qauntum state to be diagonalized :param rho: Qauntum state to be diagonalized
...@@ -88,29 +88,29 @@ def Paddle_VQSD(rho, sigma, N=2, THETA_SIZE=15, ITR=50, LR=0.1): ...@@ -88,29 +88,29 @@ def Paddle_VQSD(rho, sigma, N=2, THETA_SIZE=15, ITR=50, LR=0.1):
:param LR: Learning rate :param LR: Learning rate
:return: Diagonalized quantum state after optimization :return: Diagonalized quantum state after optimization
""" """
# Initialize PaddlePaddle dynamic graph machanism
with fluid.dygraph.guard(): # Fix the dimensions of network
# Fix the dimensions of network net = Net(shape=[THETA_SIZE], rho=rho, sigma=sigma)
net = Net(shape=[THETA_SIZE], rho=rho, sigma=sigma)
# Use Adagrad optimizer
# Use Adagrad optimizer opt = paddle.optimizer.Adagrad(learning_rate=LR, parameters=net.parameters())
opt = fluid.optimizer.AdagradOptimizer(learning_rate=LR, parameter_list=net.parameters())
# Optimization iterations
# Optimization iterations for itr in range(ITR):
for itr in range(ITR):
# Run forward propagation to calculate loss function and obtain energy spectrum
# Run forward propagation to calculate loss function and obtain energy spectrum loss, rho_tilde = net(N)
loss, rho_tilde = net(N) rho_tilde_np = rho_tilde.numpy()
rho_tilde_np = rho_tilde.numpy()
# In dynamic graph, run backward propagation to minimize loss function
# In dynamic graph, run backward propogation to minimize loss function loss.backward()
loss.backward() opt.minimize(loss)
opt.minimize(loss) opt.clear_grad()
net.clear_gradients()
# Print results
# Print results if itr % 10 == 0:
if itr % 10 == 0: print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])
print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])
return rho_tilde_np return rho_tilde_np
......
...@@ -18,6 +18,7 @@ Main ...@@ -18,6 +18,7 @@ Main
import numpy import numpy
import paddle
from paddle_quantum.VQSD.HGenerator import generate_rho_sigma from paddle_quantum.VQSD.HGenerator import generate_rho_sigma
from paddle_quantum.VQSD.Paddle_VQSD import Paddle_VQSD from paddle_quantum.VQSD.Paddle_VQSD import Paddle_VQSD
......
...@@ -17,4 +17,4 @@ Paddle Quantum Library ...@@ -17,4 +17,4 @@ Paddle Quantum Library
""" """
name = "paddle_quantum" name = "paddle_quantum"
__version__= "1.2.0" __version__ = "2.0.0"
\ No newline at end of file
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. # Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -20,18 +20,16 @@ import numpy as np ...@@ -20,18 +20,16 @@ import numpy as np
from numpy import binary_repr, eye, identity from numpy import binary_repr, eye, identity
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from paddle_quantum.simulator import StateTransfer, init_state_gen, measure_state
import paddle import paddle
from paddle.complex import kron as pp_kron from paddle import kron as pp_kron
from paddle.complex import reshape as complex_reshape from paddle import reshape as complex_reshape
from paddle.complex import matmul, transpose, trace from paddle import matmul, transpose, trace, real, imag
from paddle.complex.tensor.math import elementwise_mul from paddle import multiply
import paddle.fluid as fluid from paddle import reshape, cast, eye, zeros
from paddle.fluid import dygraph
from paddle.fluid.layers import reshape, cast, eye, zeros
from paddle.fluid.framework import ComplexVariable
from paddle_quantum.simulator import StateTranfer, init_state_gen, measure_state
from paddle_quantum.utils import dagger, pauli_str_to_matrix from paddle_quantum.utils import dagger, pauli_str_to_matrix
from paddle_quantum.intrinsic import * from paddle_quantum.intrinsic import *
from paddle_quantum.state import density_op from paddle_quantum.state import density_op
...@@ -66,58 +64,56 @@ class UAnsatz: ...@@ -66,58 +64,56 @@ class UAnsatz:
def run_state_vector(self, input_state=None, store_state=True): def run_state_vector(self, input_state=None, store_state=True):
r"""运行当前的量子线路,输入输出的形式为态矢量。 r"""运行当前的量子线路,输入输出的形式为态矢量。
Args: Args:
input_state (ComplexVariable, optional): 输入的态矢量,默认为 :math:`|00...0\rangle` input_state (Tensor, optional): 输入的态矢量,默认为 :math:`|00...0\rangle`
store_state (Bool, optional): 是否存储输出的态矢量,默认为 ``True`` ,即存储 store_state (Bool, optional): 是否存储输出的态矢量,默认为 ``True`` ,即存储
Returns: Returns:
ComplexVariable: 量子线路输出的态矢量 Tensor: 量子线路输出的态矢量
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
from paddle_quantum.state import vec
n = 2 n = 2
theta = np.ones(3) theta = np.ones(3)
input_state = np.ones(2**n)+0j
input_state = input_state / np.linalg.norm(input_state) input_state = paddle.to_tensor(vec(n))
with fluid.dygraph.guard(): theta = paddle.to_tensor(theta)
cir = UAnsatz(n)
input_state_var = fluid.dygraph.to_variable(input_state) cir.h(0)
theta = fluid.dygraph.to_variable(theta) cir.ry(theta[0], 1)
cir = UAnsatz(n) cir.rz(theta[1], 1)
cir.rx(theta[0], 0) output_state = cir.run_state_vector(input_state).numpy()
cir.ry(theta[1], 1) print(f"The output state vector is {output_state}")
cir.rz(theta[2], 1)
vec = cir.run_state_vector(input_state_var).numpy()
print(f"The output state vector is {vec}")
:: ::
The output state vector is [0.17470783-0.09544332j 0.59544332+0.32529217j 0.17470783-0.09544332j 0.59544332+0.32529217j] The output state vector is [[0.62054458+0.j 0.18316521+0.28526291j 0.62054458+0.j 0.18316521+0.28526291j]]
""" """
state = init_state_gen(self.n, 0) if input_state is None else input_state state = init_state_gen(self.n, 0) if input_state is None else input_state
old_shape = state.shape old_shape = state.shape
assert reduce(lambda x, y: x * y, old_shape) == 2 ** self.n, 'The length of the input vector is not right' assert reduce(lambda x, y: x * y, old_shape) == 2 ** self.n, 'The length of the input vector is not right'
state = complex_reshape(state, (2 ** self.n,)) state = complex_reshape(state, (2 ** self.n,))
state_conj = ComplexVariable(state.real, -state.imag) state_conj = paddle.conj(state)
assert fluid.layers.abs(paddle.complex.sum(elementwise_mul(state_conj, state)).real - 1) < 1e-8, \ assert paddle.abs(paddle.real(paddle.sum(multiply(state_conj, state))) - 1) < 1e-8, \
'Input state is not a normalized vector' 'Input state is not a normalized vector'
for history_ele in self.__history: for history_ele in self.__history:
if history_ele[0] == 'u': if history_ele[0] == 'u':
state = StateTranfer(state, 'u', history_ele[1], history_ele[2]) state = StateTransfer(state, 'u', history_ele[1], history_ele[2])
elif history_ele[0] in {'x', 'y', 'z', 'h'}: elif history_ele[0] in {'x', 'y', 'z', 'h'}:
state = StateTranfer(state, history_ele[0], history_ele[1], params=history_ele[2]) state = StateTransfer(state, history_ele[0], history_ele[1], params=history_ele[2])
elif history_ele[0] == 'SWAP': elif history_ele[0] == 'SWAP':
state = StateTranfer(state, 'SWAP', history_ele[1]) state = StateTransfer(state, 'SWAP', history_ele[1])
elif history_ele[0] == 'CNOT': elif history_ele[0] == 'CNOT':
state = StateTranfer(state, 'CNOT', history_ele[1]) state = StateTransfer(state, 'CNOT', history_ele[1])
if store_state: if store_state:
self.__state = state self.__state = state
...@@ -128,45 +124,43 @@ class UAnsatz: ...@@ -128,45 +124,43 @@ class UAnsatz:
def run_density_matrix(self, input_state=None, store_state=True): def run_density_matrix(self, input_state=None, store_state=True):
r"""运行当前的量子线路,输入输出的形式为密度矩阵。 r"""运行当前的量子线路,输入输出的形式为密度矩阵。
Args: Args:
input_state (ComplexVariable, optional): 输入的密度矩阵,默认为 :math:`|00...0\rangle \langle00...0|` input_state (Tensor, optional): 输入的密度矩阵,默认为 :math:`|00...0\rangle \langle00...0|`
store_state (bool, optional): 是否存储输出的密度矩阵,默认为 ``True`` ,即存储 store_state (bool, optional): 是否存储输出的密度矩阵,默认为 ``True`` ,即存储
Returns: Returns:
ComplexVariable: 量子线路输出的密度矩阵 Tensor: 量子线路输出的密度矩阵
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
from paddle_quantum.state import density_op
n = 1 n = 1
theta = np.ones(3) theta = np.ones(3)
input_state = np.diag(np.arange(2**n))+0j
input_state = input_state / np.trace(input_state) input_state = paddle.to_tensor(density_op(n))
with fluid.dygraph.guard(): theta = paddle.to_tensor(theta)
cir = UAnsatz(n)
input_state_var = fluid.dygraph.to_variable(input_state) cir.rx(theta[0], 0)
theta = fluid.dygraph.to_variable(theta) cir.ry(theta[1], 0)
cir = UAnsatz(n) cir.rz(theta[2], 0)
cir.rx(theta[0], 0) density_matrix = cir.run_density_matrix(input_state).numpy()
cir.ry(theta[1], 0) print(f"The output density matrix is\n{density_matrix}")
cir.rz(theta[2], 0)
density = cir.run_density_matrix(input_state_var).numpy()
print(f"The output density matrix is\n{density}")
:: ::
The output density matrix is The output density matrix is
[[ 0.35403671+0.j -0.47686058-0.03603751j] [[0.64596329+0.j 0.47686058+0.03603751j]
[-0.47686058+0.03603751j 0.64596329+0.j ]] [0.47686058-0.03603751j 0.35403671+0.j ]]
""" """
state = dygraph.to_variable(density_op(self.n)) if input_state is None else input_state state = paddle.to_tensor(density_op(self.n)) if input_state is None else input_state
assert state.real.shape == [2 ** self.n, 2 ** self.n], "The dimension is not right" assert paddle.real(state).shape == [2 ** self.n, 2 ** self.n], "The dimension is not right"
state = matmul(self.U, matmul(state, dagger(self.U))) state = matmul(self.U, matmul(state, dagger(self.U)))
if store_state: if store_state:
...@@ -179,23 +173,22 @@ class UAnsatz: ...@@ -179,23 +173,22 @@ class UAnsatz:
@property @property
def U(self): def U(self):
r"""量子线路的酉矩阵形式。 r"""量子线路的酉矩阵形式。
Returns: Returns:
ComplexVariable: 当前线路的酉矩阵表示 Tensor: 当前线路的酉矩阵表示
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
n = 2 n = 2
with fluid.dygraph.guard(): cir = UAnsatz(2)
cir = UAnsatz(2) cir.h(0)
cir.h(0) cir.cnot([0, 1])
cir.cnot([0, 1]) unitary_matrix = cir.U
matrix = cir.U print("The unitary matrix of the circuit for Bell state preparation is\n", unitary_matrix.numpy())
print("The unitary matrix of the circuit for Bell state preparation is\n",matrix.numpy())
:: ::
...@@ -205,22 +198,24 @@ class UAnsatz: ...@@ -205,22 +198,24 @@ class UAnsatz:
[ 0. +0.j 0.70710678+0.j 0. +0.j -0.70710678+0.j] [ 0. +0.j 0.70710678+0.j 0. +0.j -0.70710678+0.j]
[ 0.70710678+0.j 0. +0.j -0.70710678+0.j 0. +0.j]] [ 0.70710678+0.j 0. +0.j -0.70710678+0.j 0. +0.j]]
""" """
state = ComplexVariable(eye(2 ** self.n, dtype='float64'), zeros([2 ** self.n, 2 ** self.n], dtype='float64')) state = eye(2 ** self.n, dtype='float64')
state = paddle.cast(state, 'complex128')
shape = (2 ** self.n, 2 ** self.n) shape = (2 ** self.n, 2 ** self.n)
num_ele = reduce(lambda x, y: x * y, shape) num_ele = reduce(lambda x, y: x * y, shape)
state = ComplexVariable(reshape(state.real, [num_ele]), reshape(state.imag, [num_ele])) state = paddle.reshape(state, [num_ele])
for history_ele in self.__history: for history_ele in self.__history:
if history_ele[0] == 'u': if history_ele[0] == 'u':
state = StateTranfer(state, 'u', history_ele[1], history_ele[2]) state = StateTransfer(state, 'u', history_ele[1], history_ele[2])
elif history_ele[0] in {'x', 'y', 'z', 'h'}: elif history_ele[0] in {'x', 'y', 'z', 'h'}:
state = StateTranfer(state, history_ele[0], history_ele[1], params=history_ele[2]) state = StateTransfer(state, history_ele[0], history_ele[1], params=history_ele[2])
elif history_ele[0] == 'SWAP': elif history_ele[0] == 'SWAP':
state = StateTranfer(state, 'SWAP', history_ele[1]) state = StateTransfer(state, 'SWAP', history_ele[1])
elif history_ele[0] == 'CNOT': elif history_ele[0] == 'CNOT':
state = StateTranfer(state, 'CNOT', history_ele[1]) state = StateTransfer(state, 'CNOT', history_ele[1])
return ComplexVariable(reshape(state.real, shape), reshape(state.imag, shape)) return paddle.reshape(state, shape)
""" """
Common Gates Common Gates
...@@ -230,93 +225,91 @@ class UAnsatz: ...@@ -230,93 +225,91 @@ class UAnsatz:
r"""添加关于 x 轴的单量子比特旋转门。 r"""添加关于 x 轴的单量子比特旋转门。
其矩阵形式为: 其矩阵形式为:
.. math:: .. math::
\begin{bmatrix} \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} \\ -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix} \begin{bmatrix} \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} \\ -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix}
Args: Args:
theta (Variable): 旋转角度 theta (Tensor): 旋转角度
which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
theta = np.array([np.pi], np.float64) theta = np.array([np.pi], np.float64)
with fluid.dygraph.guard(): theta = paddle.to_tensor(theta)
theta = fluid.dygraph.to_variable(theta) num_qubits = 1
num_qubits = 1 cir = UAnsatz(num_qubits)
cir = UAnsatz(num_qubits) which_qubit = 0
which_qubit = 0 cir.rx(theta[0], which_qubit)
cir.rx(theta[0], which_qubit)
""" """
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['u', [which_qubit], [theta, self.__history.append(['u', [which_qubit], [theta,
dygraph.to_variable(np.array([-math.pi / 2])), paddle.to_tensor(np.array([-math.pi / 2])),
dygraph.to_variable(np.array([math.pi / 2]))]]) paddle.to_tensor(np.array([math.pi / 2]))]])
def ry(self, theta, which_qubit): def ry(self, theta, which_qubit):
r"""添加关于 y 轴的单量子比特旋转门。 r"""添加关于 y 轴的单量子比特旋转门。
其矩阵形式为: 其矩阵形式为:
.. math:: .. math::
\begin{bmatrix} \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\ \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix} \begin{bmatrix} \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\ \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix}
Args: Args:
theta (Variable): 旋转角度 theta (Tensor): 旋转角度
which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
theta = np.array([np.pi], np.float64) theta = np.array([np.pi], np.float64)
with fluid.dygraph.guard(): theta = paddle.to_tensor(theta)
theta = fluid.dygraph.to_variable(theta) num_qubits = 1
num_qubits = 1 cir = UAnsatz(num_qubits)
cir = UAnsatz(num_qubits) which_qubit = 0
which_qubit = 0 cir.ry(theta[0], which_qubit)
cir.ry(theta[0], which_qubit)
""" """
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['u', [which_qubit], [theta, self.__history.append(['u', [which_qubit], [theta,
dygraph.to_variable(np.array([0.0])), paddle.to_tensor(np.array([0.0])),
dygraph.to_variable(np.array([0.0]))]]) paddle.to_tensor(np.array([0.0]))]])
def rz(self, theta, which_qubit): def rz(self, theta, which_qubit):
r"""添加关于 z 轴的单量子比特旋转门。 r"""添加关于 z 轴的单量子比特旋转门。
其矩阵形式为: 其矩阵形式为:
.. math:: .. math::
\begin{bmatrix} 1 & 0 \\ 0 & e^{i\theta} \end{bmatrix} \begin{bmatrix} 1 & 0 \\ 0 & e^{i\theta} \end{bmatrix}
Args: Args:
theta (Variable): 旋转角度 theta (Tensor): 旋转角度
which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
theta = np.array([np.pi], np.float64) theta = np.array([np.pi], np.float64)
with fluid.dygraph.guard(): theta = paddle.to_tensor(theta)
theta = fluid.dygraph.to_variable(theta) num_qubits = 1
num_qubits = 1 cir = UAnsatz(num_qubits)
cir = UAnsatz(num_qubits) which_qubit = 0
which_qubit = 0 cir.rz(theta[0], which_qubit)
cir.ry(theta[0], which_qubit)
""" """
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['u', [which_qubit], [dygraph.to_variable(np.array([0.0])), self.__history.append(['u', [which_qubit], [paddle.to_tensor(np.array([0.0])),
dygraph.to_variable(np.array([0.0])), paddle.to_tensor(np.array([0.0])),
theta]]) theta]])
def cnot(self, control): def cnot(self, control):
...@@ -325,7 +318,7 @@ class UAnsatz: ...@@ -325,7 +318,7 @@ class UAnsatz:
对于 2 量子比特的量子线路,当 ``control`` 为 ``[0, 1]`` 时,其矩阵形式为: 对于 2 量子比特的量子线路,当 ``control`` 为 ``[0, 1]`` 时,其矩阵形式为:
.. math:: .. math::
\begin{align} \begin{align}
CNOT &=|0\rangle \langle 0|\otimes I + |1 \rangle \langle 1|\otimes X\\ CNOT &=|0\rangle \langle 0|\otimes I + |1 \rangle \langle 1|\otimes X\\
&=\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{bmatrix} &=\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{bmatrix}
...@@ -335,14 +328,13 @@ class UAnsatz: ...@@ -335,14 +328,13 @@ class UAnsatz:
control (list): 作用在的 qubit 的编号,``control[0]`` 为控制位,``control[1]`` 为目标位,其值都应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 control (list): 作用在的 qubit 的编号,``control[0]`` 为控制位,``control[1]`` 为目标位,其值都应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
num_qubits = 2 num_qubits = 2
with fluid.dygraph.guard(): cir = UAnsatz(num_qubits)
cir = UAnsatz(num_qubits) cir.cnot([0, 1])
cir.cnot([0, 1])
""" """
assert 0 <= control[0] < self.n and 0 <= control[1] < self.n,\ assert 0 <= control[0] < self.n and 0 <= control[1] < self.n,\
"the qubit should >= 0 and < n(the number of qubit)" "the qubit should >= 0 and < n(the number of qubit)"
...@@ -361,17 +353,16 @@ class UAnsatz: ...@@ -361,17 +353,16 @@ class UAnsatz:
\end{align} \end{align}
Args: Args:
control (list): 作用在的 qubit 的编号,``control[0]`` 和``control[1]`` 是想要交换的位,其值都应该在 :math:`[0, n)`范围内, :math:`n` 为该量子线路的量子比特数 control (list): 作用在的 qubit 的编号,``control[0]`` 和 ``control[1]`` 是想要交换的位,其值都应该在 :math:`[0, n)`范围内, :math:`n` 为该量子线路的量子比特数
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
num_qubits = 2 num_qubits = 2
with fluid.dygraph.guard(): cir = UAnsatz(num_qubits)
cir = UAnsatz(num_qubits) cir.swap([0, 1])
cir.swap([0, 1])
""" """
assert 0 <= control[0] < self.n and 0 <= control[1] < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= control[0] < self.n and 0 <= control[1] < self.n, "the qubit should >= 0 and < n(the number of qubit)"
assert control[0] != control[1], "the indices needed to be swapped should not be the same" assert control[0] != control[1], "the indices needed to be swapped should not be the same"
...@@ -381,23 +372,28 @@ class UAnsatz: ...@@ -381,23 +372,28 @@ class UAnsatz:
r"""添加单量子比特 X 门。 r"""添加单量子比特 X 门。
其矩阵形式为: 其矩阵形式为:
.. math:: .. math::
\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}
Args: Args:
which_qubit (int): 作用在的qubit的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 which_qubit (int): 作用在的qubit的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
.. code-block:: python .. code-block:: python
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
with fluid.dygraph.guard(): num_qubits = 1
num_qubits = 1 cir = UAnsatz(num_qubits)
cir = UAnsatz(num_qubits) which_qubit = 0
which_qubit = 0 cir.x(which_qubit)
cir.x(which_qubit) cir.run_state_vector()
print(cir.measure(shots = 0))
::
{'0': 0.0, '1': 1.0}
""" """
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['x', [which_qubit], None]) self.__history.append(['x', [which_qubit], None])
...@@ -406,23 +402,28 @@ class UAnsatz: ...@@ -406,23 +402,28 @@ class UAnsatz:
r"""添加单量子比特 Y 门。 r"""添加单量子比特 Y 门。
其矩阵形式为: 其矩阵形式为:
.. math:: .. math::
\begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix} \begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix}
Args: Args:
which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
.. code-block:: python .. code-block:: python
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
with fluid.dygraph.guard(): num_qubits = 1
num_qubits = 1 cir = UAnsatz(num_qubits)
cir = UAnsatz(num_qubits) which_qubit = 0
which_qubit = 0 cir.y(which_qubit)
cir.y(which_qubit) cir.run_state_vector()
print(cir.measure(shots = 0))
::
{'0': 0.0, '1': 1.0}
""" """
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['y', [which_qubit], None]) self.__history.append(['y', [which_qubit], None])
...@@ -431,23 +432,28 @@ class UAnsatz: ...@@ -431,23 +432,28 @@ class UAnsatz:
r"""添加单量子比特 Z 门。 r"""添加单量子比特 Z 门。
其矩阵形式为: 其矩阵形式为:
.. math:: .. math::
\begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix} \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}
Args: Args:
which_qubit (int): 作用在的qubit的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 which_qubit (int): 作用在的qubit的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
.. code-block:: python .. code-block:: python
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
with fluid.dygraph.guard(): num_qubits = 1
num_qubits = 1 cir = UAnsatz(num_qubits)
cir = UAnsatz(num_qubits) which_qubit = 0
which_qubit = 0 cir.z(which_qubit)
cir.z(which_qubit) cir.run_state_vector()
print(cir.measure(shots = 0))
::
{'0': 1.0, '1': 0.0}
""" """
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['z', [which_qubit], None]) self.__history.append(['z', [which_qubit], None])
...@@ -458,7 +464,7 @@ class UAnsatz: ...@@ -458,7 +464,7 @@ class UAnsatz:
其矩阵形式为: 其矩阵形式为:
.. math:: .. math::
H = \frac{1}{\sqrt{2}}\begin{bmatrix} 1&1\\1&-1 \end{bmatrix} H = \frac{1}{\sqrt{2}}\begin{bmatrix} 1&1\\1&-1 \end{bmatrix}
Args: Args:
...@@ -473,16 +479,16 @@ class UAnsatz: ...@@ -473,16 +479,16 @@ class UAnsatz:
其矩阵形式为: 其矩阵形式为:
.. math:: .. math::
S = \begin{bmatrix} 1&0\\0&i \end{bmatrix} S = \begin{bmatrix} 1&0\\0&i \end{bmatrix}
Args: Args:
which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
""" """
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['u', [which_qubit], [dygraph.to_variable(np.array([0.0])), self.__history.append(['u', [which_qubit], [paddle.to_tensor(np.array([0.0])),
dygraph.to_variable(np.array([0.0])), paddle.to_tensor(np.array([0.0])),
dygraph.to_variable(np.array([math.pi / 2]))]]) paddle.to_tensor(np.array([math.pi / 2]))]])
def t(self, which_qubit): def t(self, which_qubit):
r"""添加一个单量子比特的 T 门。 r"""添加一个单量子比特的 T 门。
...@@ -497,9 +503,9 @@ class UAnsatz: ...@@ -497,9 +503,9 @@ class UAnsatz:
which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
""" """
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['u', [which_qubit], [dygraph.to_variable(np.array([0.0])), self.__history.append(['u', [which_qubit], [paddle.to_tensor(np.array([0.0])),
dygraph.to_variable(np.array([0.0])), paddle.to_tensor(np.array([0.0])),
dygraph.to_variable(np.array([math.pi / 4]))]]) paddle.to_tensor(np.array([math.pi / 4]))]])
def u3(self, theta, phi, lam, which_qubit): def u3(self, theta, phi, lam, which_qubit):
r"""添加一个单量子比特的旋转门。 r"""添加一个单量子比特的旋转门。
...@@ -507,7 +513,7 @@ class UAnsatz: ...@@ -507,7 +513,7 @@ class UAnsatz:
其矩阵形式为: 其矩阵形式为:
.. math:: .. math::
\begin{align} \begin{align}
U3(\theta, \phi, \lambda) = U3(\theta, \phi, \lambda) =
\begin{bmatrix} \begin{bmatrix}
...@@ -517,9 +523,9 @@ class UAnsatz: ...@@ -517,9 +523,9 @@ class UAnsatz:
\end{align} \end{align}
Args: Args:
theta (Variable): 旋转角度 :math:`\theta` 。 theta (Tensor): 旋转角度 :math:`\theta` 。
phi (Variable): 旋转角度 :math:`\phi` 。 phi (Tensor): 旋转角度 :math:`\phi` 。
lam (Variable): 旋转角度 :math:`\lambda` 。 lam (Tensor): 旋转角度 :math:`\lambda` 。
which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数 which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子线路的量子比特数
""" """
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)" assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
...@@ -529,7 +535,7 @@ class UAnsatz: ...@@ -529,7 +535,7 @@ class UAnsatz:
r"""添加 2-qubit 通用门,这个通用门需要 15 个参数。 r"""添加 2-qubit 通用门,这个通用门需要 15 个参数。
Args: Args:
theta (Variable): 2-qubit 通用门的参数,其维度为 ``(15, )`` theta (Tensor): 2-qubit 通用门的参数,其维度为 ``(15, )``
which_qubits(list): 作用的量子比特编号 which_qubits(list): 作用的量子比特编号
代码示例: 代码示例:
...@@ -537,16 +543,14 @@ class UAnsatz: ...@@ -537,16 +543,14 @@ class UAnsatz:
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
n = 2 n = 2
theta = np.ones(15) theta = paddle.to_tensor(np.ones(15))
with fluid.dygraph.guard(): cir = UAnsatz(n)
theta = fluid.dygraph.to_variable(theta) cir.universal_2_qubit_gate(theta, [0, 1])
cir = UAnsatz(n) cir.run_state_vector()
cir.universal_2_qubit_gate(fluid.dygraph.to_variable(theta), [0, 1]) print(cir.measure(shots = 0))
cir.run_state_vector()
print(cir.measure(shots = 0))
:: ::
...@@ -615,7 +619,7 @@ class UAnsatz: ...@@ -615,7 +619,7 @@ class UAnsatz:
参考: https://cds.cern.ch/record/708846/files/0401178.pdf 参考: https://cds.cern.ch/record/708846/files/0401178.pdf
Args: Args:
theta (Variable): 3-qubit 通用门的参数,其维度为 ``(81, )`` theta (Tensor): 3-qubit 通用门的参数,其维度为 ``(81, )``
which_qubits(list): 作用的量子比特编号 which_qubits(list): 作用的量子比特编号
代码示例: 代码示例:
...@@ -623,16 +627,14 @@ class UAnsatz: ...@@ -623,16 +627,14 @@ class UAnsatz:
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
n = 3 n = 3
theta = np.ones(81) theta = paddle.to_tensor(np.ones(81))
with fluid.dygraph.guard(): cir = UAnsatz(n)
theta = fluid.dygraph.to_variable(theta) cir.universal_3_qubit_gate(theta, [0, 1, 2])
cir = UAnsatz(n) cir.run_state_vector()
cir.universal_3_qubit_gate(fluid.dygraph.to_variable(theta), [0, 1, 2]) print(cir.measure(shots = 0))
cir.run_state_vector()
print(cir.measure(shots = 0))
:: ::
...@@ -641,8 +643,8 @@ class UAnsatz: ...@@ -641,8 +643,8 @@ class UAnsatz:
assert len(which_qubits) == 3, "You should add this gate on three qubits" assert len(which_qubits) == 3, "You should add this gate on three qubits"
assert len(theta) == 81, "The length of theta is supposed to be 81" assert len(theta) == 81, "The length of theta is supposed to be 81"
psi = fluid.layers.reshape(x=theta[: 60], shape=[4, 15]) psi = paddle.reshape(x=theta[: 60], shape=[4, 15])
phi = fluid.layers.reshape(x=theta[60:], shape=[7, 3]) phi = paddle.reshape(x=theta[60:], shape=[7, 3])
self.universal_2_qubit_gate(psi[0], which_qubits[:2]) self.universal_2_qubit_gate(psi[0], which_qubits[:2])
self.u3(phi[0][0], phi[0][1], phi[0][2], which_qubits[2]) self.u3(phi[0][0], phi[0][1], phi[0][2], which_qubits[2])
...@@ -737,23 +739,22 @@ class UAnsatz: ...@@ -737,23 +739,22 @@ class UAnsatz:
which_qubits (list, optional): 要测量的qubit的编号,默认全都测量 which_qubits (list, optional): 要测量的qubit的编号,默认全都测量
shots (int, optional): 该量子线路输出的量子态的测量次数,默认为 1024 次;若为 0,则返回测量结果的精确概率分布 shots (int, optional): 该量子线路输出的量子态的测量次数,默认为 1024 次;若为 0,则返回测量结果的精确概率分布
plot (bool, optional): 是否绘制测量结果图,默认为 ``False`` ,即不绘制 plot (bool, optional): 是否绘制测量结果图,默认为 ``False`` ,即不绘制
Returns: Returns:
dict: 测量的结果 dict: 测量的结果
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
with paddle.fluid.dygraph.guard(): cir = UAnsatz(2)
cir = UAnsatz(2) cir.h(0)
cir.h(0) cir.cnot([0,1])
cir.cnot([0,1]) cir.run_state_vector()
cir.run_state_vector() result = cir.measure(shots = 2048, which_qubits = [1])
result = cir.measure(shots = 2048, which_qubits = [1]) print(f"The results of measuring qubit 1 2048 times are {result}")
print(f"The results of measuring qubit 1 2048 times are {result}")
:: ::
...@@ -763,13 +764,12 @@ class UAnsatz: ...@@ -763,13 +764,12 @@ class UAnsatz:
import paddle import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
with paddle.fluid.dygraph.guard(): cir = UAnsatz(2)
cir = UAnsatz(2) cir.h(0)
cir.h(0) cir.cnot([0,1])
cir.cnot([0,1]) cir.run_state_vector()
cir.run_state_vector() result = cir.measure(shots = 0, which_qubits = [1])
result = cir.measure(shots = 0, which_qubits = [1]) print(f"The probability distribution of measurement results on qubit 1 is {result}")
print(f"The probability distribution of measurement results on qubit 1 is {result}")
:: ::
...@@ -780,7 +780,7 @@ class UAnsatz: ...@@ -780,7 +780,7 @@ class UAnsatz:
elif self.__run_state == 'density_matrix': elif self.__run_state == 'density_matrix':
# Take the diagonal of the density matrix as a probability distribution # Take the diagonal of the density matrix as a probability distribution
diag = np.diag(self.__state.numpy()) diag = np.diag(self.__state.numpy())
state = fluid.dygraph.to_variable(np.sqrt(diag)) state = paddle.to_tensor(np.sqrt(diag))
else: else:
# Raise error # Raise error
raise ValueError("no state for measurement; please run the circuit first") raise ValueError("no state for measurement; please run the circuit first")
...@@ -789,7 +789,7 @@ class UAnsatz: ...@@ -789,7 +789,7 @@ class UAnsatz:
dic2to10, dic10to2 = dic_between2and10(self.n) dic2to10, dic10to2 = dic_between2and10(self.n)
result = {} result = {}
for i in range(2 ** self.n): for i in range(2 ** self.n):
result[dic10to2[i]] = (state.real[i] ** 2 + state.imag[i] ** 2).numpy()[0] result[dic10to2[i]] = (real(state)[i] ** 2 + imag(state)[i] ** 2).numpy()[0]
if which_qubits is not None: if which_qubits is not None:
new_result = [(self.__process_string(key, which_qubits), value) for key, value in result.items()] new_result = [(self.__process_string(key, which_qubits), value) for key, value in result.items()]
...@@ -816,66 +816,37 @@ class UAnsatz: ...@@ -816,66 +816,37 @@ class UAnsatz:
Args: Args:
H (list): 可观测量的相关信息 H (list): 可观测量的相关信息
Returns: Returns:
Variable: 量子线路输出的量子态关于 H 的期望值 Tensor: 量子线路输出的量子态关于 H 的期望值
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
n = 5 n = 5
H_info = [[0.1, 'x1'], [0.2, 'y0,z4']] H_info = [[0.1, 'x1'], [0.2, 'y0,z4']]
theta = np.ones(3) theta = paddle.to_tensor(np.ones(3))
input_state = np.ones(2**n)+0j cir = UAnsatz(n)
input_state = input_state / np.linalg.norm(input_state) cir.rx(theta[0], 0)
with fluid.dygraph.guard(): cir.rz(theta[1], 1)
input_state_var = fluid.dygraph.to_variable(input_state) cir.rx(theta[2], 2)
theta = fluid.dygraph.to_variable(theta) cir.run_state_vector()
cir = UAnsatz(n) expect_value = cir.expecval(H_info).numpy()
cir.rx(theta[0], 0) print(f'Calculated expectation value of {H_info} is {expect_value}')
cir.rz(theta[1], 1)
cir.rx(theta[2], 2)
cir.run_state_vector(input_state_var)
expect_value = cir.expecval(H_info).numpy()
print(f'Calculated expectation value of {H_info} is {expect_value}')
:: ::
Calculated expectation value of [[0.1, 'x1'], [0.2, 'y0,z4']] is [0.05403023] Calculated expectation value of [[0.1, 'x1'], [0.2, 'y0,z4']] is [-0.1682942]
.. code-block:: python
import numpy as np
from paddle import fluid
from paddle_quantum.circuit import UAnsatz
n = 5
H_info = [[0.1, 'x1'], [0.2, 'y0,z4']]
theta = np.ones(3)
input_state = np.diag(np.arange(2**n))+0j
input_state = input_state / np.trace(input_state)
with fluid.dygraph.guard():
input_state_var = fluid.dygraph.to_variable(input_state)
theta = fluid.dygraph.to_variable(theta)
cir = UAnsatz(n)
cir.rx(theta[0], 0)
cir.ry(theta[1], 1)
cir.rz(theta[2], 2)
cir.run_density_matrix(input_state_var)
expect_value = cir.expecval(H_info).numpy()
print(f'Calculated expectation value of {H_info} is {expect_value}')
::
Calculated expectation value of [[0.1, 'x1'], [0.2, 'y0,z4']] is [-0.02171538]
""" """
if self.__run_state == 'state_vector': if self.__run_state == 'state_vector':
return vec_expecval(H, self.__state).real return real(vec_expecval(H, self.__state))
elif self.__run_state == 'density_matrix': elif self.__run_state == 'density_matrix':
state = self.__state state = self.__state
H_mat = fluid.dygraph.to_variable(pauli_str_to_matrix(H, self.n)) H_mat = paddle.to_tensor(pauli_str_to_matrix(H, self.n))
return trace(matmul(state, H_mat)).real return real(trace(matmul(state, H_mat)))
else: else:
# Raise error # Raise error
raise ValueError("no state for measurement; please run the circuit first") raise ValueError("no state for measurement; please run the circuit first")
...@@ -890,15 +861,14 @@ class UAnsatz: ...@@ -890,15 +861,14 @@ class UAnsatz:
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
with paddle.fluid.dygraph.guard(): cir = UAnsatz(2)
cir = UAnsatz(2) cir.superposition_layer()
cir.superposition_layer() cir.run_state_vector()
cir.run_state_vector() result = cir.measure(shots = 0)
result = cir.measure(shots = 0) print(f"The probability distribution of measurement results on both qubits is {result}")
print(f"The probability distribution of measurement results on both qubits is {result}")
:: ::
...@@ -913,21 +883,20 @@ class UAnsatz: ...@@ -913,21 +883,20 @@ class UAnsatz:
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
with paddle.fluid.dygraph.guard(): cir = UAnsatz(2)
cir = UAnsatz(2) cir.weak_superposition_layer()
cir.weak_superposition_layer() cir.run_state_vector()
cir.run_state_vector() result = cir.measure(shots = 0)
result = cir.measure(shots = 0) print(f"The probability distribution of measurement results on both qubits is {result}")
print(f"The probability distribution of measurement results on both qubits is {result}")
:: ::
The probability distribution of measurement results on both qubits is {'00': 0.7285533905932737, '01': 0.12500000000000003, '10': 0.12500000000000003, '11': 0.021446609406726238} The probability distribution of measurement results on both qubits is {'00': 0.7285533905932737, '01': 0.12500000000000003, '10': 0.12500000000000003, '11': 0.021446609406726238}
""" """
_theta = fluid.dygraph.to_variable(np.array([np.pi / 4])) # Used in fixed Ry gate _theta = paddle.to_tensor(np.array([np.pi / 4])) # Used in fixed Ry gate
for i in range(self.n): for i in range(self.n):
self.ry(_theta, i) self.ry(_theta, i)
...@@ -941,7 +910,7 @@ class UAnsatz: ...@@ -941,7 +910,7 @@ class UAnsatz:
``theta`` 的维度为 ``(depth, n, 1)`` ``theta`` 的维度为 ``(depth, n, 1)``
Args: Args:
theta (Variable): Ry 门的旋转角度 theta (Tensor): Ry 门的旋转角度
depth (int): 纠缠层的深度 depth (int): 纠缠层的深度
which_qubits(list): 作用的量子比特编号 which_qubits(list): 作用的量子比特编号
...@@ -950,18 +919,17 @@ class UAnsatz: ...@@ -950,18 +919,17 @@ class UAnsatz:
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
n = 2 n = 2
DEPTH = 3 DEPTH = 3
theta = np.ones([DEPTH, n, 1]) theta = np.ones([DEPTH, n, 1])
with fluid.dygraph.guard(): theta = paddle.to_tensor(theta)
theta = fluid.dygraph.to_variable(theta) cir = UAnsatz(n)
cir = UAnsatz(n) cir.real_entangled_layer(paddle.to_tensor(theta), DEPTH, [0, 1])
cir.real_entangled_layer(fluid.dygraph.to_variable(theta), DEPTH, [0, 1]) cir.run_state_vector()
cir.run_state_vector() print(cir.measure(shots = 0))
print(cir.measure(shots = 0))
:: ::
{'00': 2.52129874867343e-05, '01': 0.295456784923382, '10': 0.7045028818254718, '11': 1.5120263659845063e-05} {'00': 2.52129874867343e-05, '01': 0.295456784923382, '10': 0.7045028818254718, '11': 1.5120263659845063e-05}
...@@ -969,7 +937,7 @@ class UAnsatz: ...@@ -969,7 +937,7 @@ class UAnsatz:
assert self.n > 1, 'you need at least 2 qubits' assert self.n > 1, 'you need at least 2 qubits'
assert len(theta.shape) == 3, 'the shape of theta is not right' assert len(theta.shape) == 3, 'the shape of theta is not right'
assert theta.shape[2] == 1, 'the shape of theta is not right' assert theta.shape[2] == 1, 'the shape of theta is not right'
#assert theta.shape[1] == self.n, 'the shape of theta is not right' # assert theta.shape[1] == self.n, 'the shape of theta is not right'
assert theta.shape[0] == depth, 'the depth of theta has a mismatch' assert theta.shape[0] == depth, 'the depth of theta has a mismatch'
if which_qubits is None: if which_qubits is None:
...@@ -987,32 +955,31 @@ class UAnsatz: ...@@ -987,32 +955,31 @@ class UAnsatz:
Note: Note:
这一层量子门的数学表示形式为复数酉矩阵。 这一层量子门的数学表示形式为复数酉矩阵。
Attention: Attention:
``theta`` 的维度为 ``(depth, n, 3)`` ,最低维内容为对应的 ``u3`` 的参数 ``(theta, phi, lam)`` ``theta`` 的维度为 ``(depth, n, 3)`` ,最低维内容为对应的 ``u3`` 的参数 ``(theta, phi, lam)``
Args: Args:
theta (Variable): U3 门的旋转角度 theta (Tensor): U3 门的旋转角度
depth (int): 纠缠层的深度 depth (int): 纠缠层的深度
which_qubits(list): 作用的量子比特编号 which_qubits(list): 作用的量子比特编号
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
n = 2 n = 2
DEPTH = 3 DEPTH = 3
theta = np.ones([DEPTH, n, 1]) theta = np.ones([DEPTH, n, 3])
with fluid.dygraph.guard(): theta = paddle.to_tensor(theta)
theta = fluid.dygraph.to_variable(theta) cir = UAnsatz(n)
cir = UAnsatz(n) cir.complex_entangled_layer(paddle.to_tensor(theta), DEPTH, [0, 1])
cir.complex_entangled_layer(fluid.dygraph.to_variable(theta), DEPTH, [0, 1]) cir.run_state_vector()
cir.run_state_vector() print(cir.measure(shots = 0))
print(cir.measure(shots = 0))
:: ::
{'00': 0.15032627279218896, '01': 0.564191201239618, '10': 0.03285998070292556, '11': 0.25262254526526823} {'00': 0.15032627279218896, '01': 0.564191201239618, '10': 0.03285998070292556, '11': 0.25262254526526823}
...@@ -1096,28 +1063,30 @@ class UAnsatz: ...@@ -1096,28 +1063,30 @@ class UAnsatz:
Note: Note:
这一层量子门的数学表示形式为实数酉矩阵。 这一层量子门的数学表示形式为实数酉矩阵。
Attention: Attention:
``theta`` 的维度为 ``(depth, n-1, 4)`` ``theta`` 的维度为 ``(depth, n-1, 4)``
Args: Args:
theta(Variable): Ry 门的旋转角度 theta(Tensor): Ry 门的旋转角度
depth(int): 纠缠层的深度 depth(int): 纠缠层的深度
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import numpy as np
import paddle
from paddle_quantum.circuit import UAnsatz
n = 4 n = 4
DEPTH = 3 DEPTH = 3
theta = np.ones([DEPTH, n-1, 4]) theta = np.ones([DEPTH, n-1, 4])
with fluid.dygraph.guard(): theta = paddle.to_tensor(theta)
theta = fluid.dygraph.to_variable(theta) cir = UAnsatz(n)
cir = UAnsatz(n) cir.real_block_layer(paddle.to_tensor(theta), DEPTH)
cir.real_block_layer(fluid.dygraph.to_variable(theta), DEPTH) cir.run_density_matrix()
cir.run_density_matrix() print(cir.measure(shots = 0, which_qubits = [0]))
print(cir.measure(shots = 0, which_qubits = [0]))
:: ::
{'0': 0.9646724056906162, '1': 0.035327594309385896} {'0': 0.9646724056906162, '1': 0.035327594309385896}
...@@ -1148,23 +1117,25 @@ class UAnsatz: ...@@ -1148,23 +1117,25 @@ class UAnsatz:
``theta`` 的维度为 ``(depth, n-1, 12)`` ``theta`` 的维度为 ``(depth, n-1, 12)``
Args: Args:
theta (Variable): U3 门的角度信息 theta (Tensor): U3 门的角度信息
depth (int): 纠缠层的深度 depth (int): 纠缠层的深度
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import numpy as np
import paddle
from paddle_quantum.circuit import UAnsatz
n = 4 n = 4
DEPTH = 3 DEPTH = 3
theta = np.ones([DEPTH, n-1, 12]) theta = np.ones([DEPTH, n-1, 12])
with fluid.dygraph.guard(): theta = paddle.to_tensor(theta)
theta = fluid.dygraph.to_variable(theta) cir = UAnsatz(n)
cir = UAnsatz(n) cir.complex_block_layer(paddle.to_tensor(theta), DEPTH)
cir.complex_block_layer(fluid.dygraph.to_variable(theta), DEPTH) cir.run_density_matrix()
cir.run_density_matrix() print(cir.measure(shots = 0, which_qubits = [0]))
print(cir.measure(shots = 0, which_qubits = [0]))
:: ::
{'0': 0.5271554811768046, '1': 0.4728445188231988} {'0': 0.5271554811768046, '1': 0.4728445188231988}
...@@ -1197,7 +1168,7 @@ def __local_H_prob(cir, hamiltonian, shots=1024): ...@@ -1197,7 +1168,7 @@ def __local_H_prob(cir, hamiltonian, shots=1024):
new_cir = UAnsatz(cir.n + 1) new_cir = UAnsatz(cir.n + 1)
input_state = pp_kron(cir.run_state_vector(store_state=False), init_state_gen(1)) input_state = pp_kron(cir.run_state_vector(store_state=False), init_state_gen(1))
# Used in fixed Rz gate # Used in fixed Rz gate
_theta = fluid.dygraph.to_variable(np.array([-np.pi / 2])) _theta = paddle.to_tensor(np.array([-np.pi / 2]))
op_list = hamiltonian.split(',') op_list = hamiltonian.split(',')
# Set up pauli measurement circuit # Set up pauli measurement circuit
...@@ -1240,34 +1211,31 @@ def H_prob(cir, H, shots=1024): ...@@ -1240,34 +1211,31 @@ def H_prob(cir, H, shots=1024):
Returns: Returns:
float: 测量得到的H的期望值 float: 测量得到的H的期望值
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
import numpy as np import numpy as np
from paddle import fluid import paddle
from paddle_quantum.circuit import UAnsatz, H_prob from paddle_quantum.circuit import UAnsatz, H_prob
n = 4 n = 4
theta = np.ones(3)
experiment_shots = 2**10 experiment_shots = 2**10
H_info = [[0.1, 'x2'], [0.3, 'y1,z3']] H_info = [[0.1, 'x2'], [0.3, 'y1,z3']]
input_state = np.ones(2**n)+0j
input_state = input_state / np.linalg.norm(input_state) theta = paddle.to_tensor(np.ones(3))
with fluid.dygraph.guard(): cir = UAnsatz(n)
theta = fluid.dygraph.to_variable(theta) cir.rx(theta[0], 0)
cir = UAnsatz(n) cir.ry(theta[1], 1)
cir.rx(theta[0], 0) cir.rz(theta[2], 1)
cir.ry(theta[1], 1) result_1 = H_prob(cir, H_info, shots = experiment_shots)
cir.rz(theta[2], 1) result_2 = H_prob(cir, H_info, shots = 0)
result_1 = H_prob(cir, H_info, shots = experiment_shots) print(f'The expectation value obtained by {experiment_shots} measurements is {result_1}')
result_2 = H_prob(cir, H_info, shots = 0) print(f'The accurate expectation value of H is {result_2}')
print(f'The expectation value obtained by {experiment_shots} measurements is {result_1}')
print(f'The accurate expectation value of H is {result_2}')
:: ::
The expectation value obtained by 1024 measurements is 0.2326171875 The expectation value obtained by 1024 measurements is 0.2177734375
The accurate expectation value of H is 0.21242202548207134 The accurate expectation value of H is 0.21242202548207134
""" """
expval = 0 expval = 0
......
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. # Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -17,9 +17,7 @@ import numpy as np ...@@ -17,9 +17,7 @@ import numpy as np
from numpy import binary_repr from numpy import binary_repr
import paddle import paddle
import paddle.fluid as fluid from paddle import multiply, add, to_tensor
from paddle.fluid.framework import ComplexVariable
from paddle.complex.tensor.math import elementwise_mul, elementwise_add
def dic_between2and10(n): def dic_between2and10(n):
...@@ -87,7 +85,7 @@ def single_H_vec(H, vec): ...@@ -87,7 +85,7 @@ def single_H_vec(H, vec):
coef, target_update = single_H_vec_i(H, dic10to2[i]) coef, target_update = single_H_vec_i(H, dic10to2[i])
index_update = dic2to10[target_update] index_update = dic2to10[target_update]
new_vec[index_update] = coef * old_vec[i] new_vec[index_update] = coef * old_vec[i]
return fluid.dygraph.to_variable(new_vec) return to_tensor(new_vec)
def H_vec(H, vec): def H_vec(H, vec):
...@@ -97,13 +95,13 @@ def H_vec(H, vec): ...@@ -97,13 +95,13 @@ def H_vec(H, vec):
Note: Note:
这是内部函数,你并不需要直接调用到该函数。 这是内部函数,你并不需要直接调用到该函数。
""" """
coefs = fluid.dygraph.to_variable(np.array([coef for coef, Hi in H], dtype=np.float64)) coefs = to_tensor(np.array([coef for coef, Hi in H], dtype=np.float64))
# Convert all strings to lowercase # Convert all strings to lowercase
H_list = [Hi.lower() for coef, Hi in H] H_list = [Hi.lower() for coef, Hi in H]
result = fluid.layers.zeros(shape=vec.shape, dtype='float64') result = paddle.zeros(shape=vec.shape, dtype='float64')
for i in range(len(coefs)): for i in range(len(coefs)):
xi = elementwise_mul(coefs[i], single_H_vec(H_list[i], vec)) xi = multiply(coefs[i], single_H_vec(H_list[i], vec))
result = elementwise_add(result, xi) result = add(result, xi)
return result return result
...@@ -114,6 +112,6 @@ def vec_expecval(H, vec): ...@@ -114,6 +112,6 @@ def vec_expecval(H, vec):
Note: Note:
这是内部函数,你并不需要直接调用到该函数。 这是内部函数,你并不需要直接调用到该函数。
""" """
vec_conj = ComplexVariable(vec.real, -vec.imag) vec_conj = paddle.conj(vec)
result = paddle.complex.sum(elementwise_mul(vec_conj, H_vec(H, vec))) result = paddle.sum(multiply(vec_conj, H_vec(H, vec)))
return result return result
...@@ -12,14 +12,13 @@ ...@@ -12,14 +12,13 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import warnings
import numpy as np import numpy as np
import paddle.fluid as fluid
import paddle import paddle
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import NKron, partial_trace, dagger from paddle_quantum.utils import NKron, partial_trace, dagger
from paddle.complex import matmul, trace, elementwise_div, kron, elementwise_add, elementwise_mul from paddle import matmul, trace, divide, kron, add, multiply
from paddle.fluid.framework import ComplexVariable from paddle import sin, cos, concat, zeros, ones, real
from paddle.fluid.layers import diag, sin, cos, concat, zeros, ones
from paddle_quantum.state import isotropic_state, bell_state from paddle_quantum.state import isotropic_state, bell_state
from math import log2, sqrt from math import log2, sqrt
from numpy import pi as PI from numpy import pi as PI
...@@ -46,8 +45,8 @@ class LoccStatus(object): ...@@ -46,8 +45,8 @@ class LoccStatus(object):
""" """
super(LoccStatus, self).__init__() super(LoccStatus, self).__init__()
if state is None and prob is None and measured_result is None: if state is None and prob is None and measured_result is None:
self.state = fluid.dygraph.to_variable(np.array([1], dtype=np.complex128)) self.state = paddle.to_tensor(np.array([1], dtype=np.complex128))
self.prob = fluid.dygraph.to_variable(np.array([1], dtype=np.float64)) self.prob = paddle.to_tensor(np.array([1], dtype=np.float64))
self.measured_result = "" self.measured_result = ""
else: else:
self.state = state self.state = state
...@@ -75,7 +74,7 @@ class LoccStatus(object): ...@@ -75,7 +74,7 @@ class LoccStatus(object):
def __repr__(self): def __repr__(self):
return f"state: {self.state.numpy()}\nprob: {self.prob.numpy()[0]}\nmeasured_result: {self.measured_result}" return f"state: {self.state.numpy()}\nprob: {self.prob.numpy()[0]}\nmeasured_result: {self.measured_result}"
def __str(self): def __str__(self):
return f"state: {self.state.numpy()}\nprob: {self.prob.numpy()[0]}\nmeasured_result: {self.measured_result}" return f"state: {self.state.numpy()}\nprob: {self.prob.numpy()[0]}\nmeasured_result: {self.measured_result}"
...@@ -158,7 +157,7 @@ class LoccAnsatz(UAnsatz): ...@@ -158,7 +157,7 @@ class LoccAnsatz(UAnsatz):
r"""添加关于 x 轴的单量子比特旋转门。 r"""添加关于 x 轴的单量子比特旋转门。
Args: Args:
theta (Variable): 量子门的角度 theta (Tensor): 量子门的角度
which_qubit (int): 添加该门量子比特编号 which_qubit (int): 添加该门量子比特编号
""" """
which_qubit = self.party[which_qubit] which_qubit = self.party[which_qubit]
...@@ -168,7 +167,7 @@ class LoccAnsatz(UAnsatz): ...@@ -168,7 +167,7 @@ class LoccAnsatz(UAnsatz):
r"""添加关于 y 轴的单量子比特旋转门。 r"""添加关于 y 轴的单量子比特旋转门。
Args: Args:
theta (Variable): 量子门的角度 theta (Tensor): 量子门的角度
which_qubit (int): 添加该门量子比特编号 which_qubit (int): 添加该门量子比特编号
""" """
which_qubit = self.party[which_qubit] which_qubit = self.party[which_qubit]
...@@ -178,7 +177,7 @@ class LoccAnsatz(UAnsatz): ...@@ -178,7 +177,7 @@ class LoccAnsatz(UAnsatz):
r"""添加关于 z 轴的单量子比特旋转门。 r"""添加关于 z 轴的单量子比特旋转门。
Args: Args:
theta (Variable): 量子门的角度 theta (Tensor): 量子门的角度
which_qubit (int): 添加该门量子比特编号 which_qubit (int): 添加该门量子比特编号
""" """
which_qubit = self.party[which_qubit] which_qubit = self.party[which_qubit]
...@@ -197,7 +196,7 @@ class LoccAnsatz(UAnsatz): ...@@ -197,7 +196,7 @@ class LoccAnsatz(UAnsatz):
r"""添加一个 SWAP 门。 r"""添加一个 SWAP 门。
Args: Args:
control (list): 作用在的 qubit 的编号,``control[0]`` 和``control[1]`` 是想要交换的位,其值都应该在 :math:`[0, m)`范围内, :math:`m` 为该参与方的量子比特数 control (list): 作用在的 qubit 的编号,``control[0]`` 和 ``control[1]`` 是想要交换的位,其值都应该在 :math:`[0, m)`范围内, :math:`m` 为该参与方的量子比特数
""" """
control = [self.party[which_qubit] for which_qubit in control] control = [self.party[which_qubit] for which_qubit in control]
super(LoccAnsatz, self).swap(control) super(LoccAnsatz, self).swap(control)
...@@ -260,9 +259,9 @@ class LoccAnsatz(UAnsatz): ...@@ -260,9 +259,9 @@ class LoccAnsatz(UAnsatz):
r"""添加一个单量子比特的旋转门。 r"""添加一个单量子比特的旋转门。
Args: Args:
theta (Variable): 旋转角度 :math:`\theta` 。 theta (Tensor): 旋转角度 :math:`\theta` 。
phi (Variable): 旋转角度 :math:`\phi` 。 phi (Tensor): 旋转角度 :math:`\phi` 。
lam (Variable): 旋转角度 :math:`\lambda` 。 lam (Tensor): 旋转角度 :math:`\lambda` 。
which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, m)` 范围内, :math:`m` 为该量子线路的量子比特数 which_qubit (int): 作用在的 qubit 的编号,其值应该在 :math:`[0, m)` 范围内, :math:`m` 为该量子线路的量子比特数
""" """
which_qubit = self.party[which_qubit] which_qubit = self.party[which_qubit]
...@@ -277,7 +276,7 @@ class LoccAnsatz(UAnsatz): ...@@ -277,7 +276,7 @@ class LoccAnsatz(UAnsatz):
def weak_superposition_layer(self): def weak_superposition_layer(self):
r"""添加一层旋转角度为 :math:`\pi/4` 的 Ry 门。 r"""添加一层旋转角度为 :math:`\pi/4` 的 Ry 门。
""" """
_theta = fluid.dygraph.to_variable(np.array([np.pi / 4])) _theta = paddle.to_tensor(np.array([np.pi / 4]))
for which_qubit in self.party.qubits: for which_qubit in self.party.qubits:
self.ry(_theta, which_qubit) self.ry(_theta, which_qubit)
...@@ -291,7 +290,7 @@ class LoccAnsatz(UAnsatz): ...@@ -291,7 +290,7 @@ class LoccAnsatz(UAnsatz):
``theta`` 的维度为 ``(depth, m, 1)`` ``theta`` 的维度为 ``(depth, m, 1)``
Args: Args:
theta (Variable): Ry 门的旋转角度 theta (Tensor): Ry 门的旋转角度
depth (int): 纠缠层的深度 depth (int): 纠缠层的深度
which_qubits(list): 作用的量子比特编号 which_qubits(list): 作用的量子比特编号
""" """
...@@ -318,7 +317,7 @@ class LoccAnsatz(UAnsatz): ...@@ -318,7 +317,7 @@ class LoccAnsatz(UAnsatz):
``theta`` 的维度为 ``(depth, m, 3)``,最低维内容为对应的 ``u3`` 的参数 ``(theta, phi, lam)`` ``theta`` 的维度为 ``(depth, m, 3)``,最低维内容为对应的 ``u3`` 的参数 ``(theta, phi, lam)``
Args: Args:
theta (Variable): U3 门的旋转角度 theta (Tensor): U3 门的旋转角度
depth (int): 纠缠层的深度 depth (int): 纠缠层的深度
which_qubits(list): 作用的量子比特编号 which_qubits(list): 作用的量子比特编号
""" """
...@@ -340,7 +339,7 @@ class LoccAnsatz(UAnsatz): ...@@ -340,7 +339,7 @@ class LoccAnsatz(UAnsatz):
r"""添加 2-qubit 通用门,这个通用门需要 15 个参数。 r"""添加 2-qubit 通用门,这个通用门需要 15 个参数。
Args: Args:
theta (Variable): 2-qubit 通用门的参数,其维度为 ``(15, )`` theta (Tensor): 2-qubit 通用门的参数,其维度为 ``(15, )``
which_qubits(list): 作用的量子比特编号 which_qubits(list): 作用的量子比特编号
""" """
...@@ -353,7 +352,7 @@ class LoccAnsatz(UAnsatz): ...@@ -353,7 +352,7 @@ class LoccAnsatz(UAnsatz):
参考: https://cds.cern.ch/record/708846/files/0401178.pdf 参考: https://cds.cern.ch/record/708846/files/0401178.pdf
Args: Args:
theta (Variable): 3-qubit 通用门的参数,其维度为 ``(81, )`` theta (Tensor): 3-qubit 通用门的参数,其维度为 ``(81, )``
which_qubits(list): 作用的量子比特编号 which_qubits(list): 作用的量子比特编号
""" """
...@@ -452,7 +451,7 @@ class LoccAnsatz(UAnsatz): ...@@ -452,7 +451,7 @@ class LoccAnsatz(UAnsatz):
self.__add_complex_block(theta[int((i - position[0]) / 2)], [i, i + 1]) self.__add_complex_block(theta[int((i - position[0]) / 2)], [i, i + 1])
class LoccNet(fluid.dygraph.Layer): class LoccNet(paddle.nn.Layer):
r"""用于设计我们的 LOCC 下的 protocol,并进行验证或者训练。 r"""用于设计我们的 LOCC 下的 protocol,并进行验证或者训练。
""" """
...@@ -467,8 +466,23 @@ class LoccNet(fluid.dygraph.Layer): ...@@ -467,8 +466,23 @@ class LoccNet(fluid.dygraph.Layer):
def set_init_status(self, state, which_qubits): def set_init_status(self, state, which_qubits):
r"""对 LoccNet 的初始 LOCC 态节点进行初始化。 r"""对 LoccNet 的初始 LOCC 态节点进行初始化。
Warning:
该方法已弃用,请使用 ``set_init_state()`` 方法以代替。
Args:
state (Tensor): 输入的量子态的矩阵形式
which_qubits (tuple or list): 该量子态所对应的量子比特,其形式为 ``(party_id, qubit_id)`` 的 ``tuple`` ,或者由其组成的 ``list``
"""
warnings.warn('The member method set_init_status() is deprecated and please use set_init_state() instead.',
DeprecationWarning)
self.set_init_state(state, which_qubits)
def set_init_state(self, state, which_qubits):
r"""对 LoccNet 的初始 LOCC 态节点进行初始化。
Args: Args:
state (ComplexVariable): 输入的量子态的矩阵形式 state (Tensor): 输入的量子态的矩阵形式
which_qubits (tuple or list): 该量子态所对应的量子比特,其形式为 ``(party_id, qubit_id)`` 的 ``tuple`` ,或者由其组成的 ``list`` which_qubits (tuple or list): 该量子态所对应的量子比特,其形式为 ``(party_id, qubit_id)`` 的 ``tuple`` ,或者由其组成的 ``list``
""" """
if isinstance(which_qubits, tuple): if isinstance(which_qubits, tuple):
...@@ -552,7 +566,7 @@ class LoccNet(fluid.dygraph.Layer): ...@@ -552,7 +566,7 @@ class LoccNet(fluid.dygraph.Layer):
Args: Args:
status (LoccStatus or list): 输入的 LOCC 态节点,其类型应该为 ``LoccStatus`` 或者由其组成的 ``list`` status (LoccStatus or list): 输入的 LOCC 态节点,其类型应该为 ``LoccStatus`` 或者由其组成的 ``list``
state (ComplexVariable): 输入的量子态的矩阵形式 state (Tensor): 输入的量子态的矩阵形式
which_qubits (tuple or list): 指定需要被重置的量子比特编号,其形式为 ``(party_id, qubit_id)`` 的 ``tuple``,或者由其组成的 ``list`` which_qubits (tuple or list): 指定需要被重置的量子比特编号,其形式为 ``(party_id, qubit_id)`` 的 ``tuple``,或者由其组成的 ``list``
Returns: Returns:
...@@ -664,63 +678,63 @@ class LoccNet(fluid.dygraph.Layer): ...@@ -664,63 +678,63 @@ class LoccNet(fluid.dygraph.Layer):
r"""进行参数化的测量。 r"""进行参数化的测量。
Args: Args:
state (ComplexVariable): 输入的量子态 state (Tensor): 输入的量子态
which_qubits (list): 测量作用的量子比特编号 which_qubits (list): 测量作用的量子比特编号
result_desired (list): 期望得到的测量结果,如 ``"0"``、``"1"`` 或者 ``["0", "1"]`` result_desired (str): 期望得到的测量结果
theta (Variable): 测量运算的参数 theta (Tensor): 测量运算的参数
Returns: Returns:
ComplexVariable: 测量坍塌后的量子态 Tensor: 测量坍塌后的量子态
Variable:测量坍塌得到的概率 Tensor:测量坍塌得到的概率
list: 测量得到的结果(0 或 1) str: 测量得到的结果
""" """
n = self.get_qubit_number() n = self.get_qubit_number()
assert len(which_qubits) == len(result_desired), \ assert len(which_qubits) == len(result_desired), \
"the length of qubits wanted to be measured and the result desired should be same" "the length of qubits wanted to be measured and the result desired should be same"
op_list = [fluid.dygraph.to_variable(np.eye(2, dtype=np.complex128))] * n op_list = [paddle.to_tensor(np.eye(2, dtype=np.complex128))] * n
for idx in range(0, len(which_qubits)): for idx in range(0, len(which_qubits)):
i = which_qubits[idx] i = which_qubits[idx]
ele = result_desired[idx] ele = result_desired[idx]
if int(ele) == 0: if int(ele) == 0:
basis0 = fluid.dygraph.to_variable(np.array([[1, 0], [0, 0]], dtype=np.complex128)) basis0 = paddle.to_tensor(np.array([[1, 0], [0, 0]], dtype=np.complex128))
basis1 = fluid.dygraph.to_variable(np.array([[0, 0], [0, 1]], dtype=np.complex128)) basis1 = paddle.to_tensor(np.array([[0, 0], [0, 1]], dtype=np.complex128))
rho0 = elementwise_mul(basis0, cos(theta[idx])) rho0 = multiply(basis0, cos(theta[idx]))
rho1 = elementwise_mul(basis1, sin(theta[idx])) rho1 = multiply(basis1, sin(theta[idx]))
rho = elementwise_add(rho0, rho1) rho = add(rho0, rho1)
op_list[i] = rho op_list[i] = rho
elif int(ele) == 1: elif int(ele) == 1:
# rho = diag(concat([cos(theta[idx]), sin(theta[idx])])) # rho = diag(concat([cos(theta[idx]), sin(theta[idx])]))
# rho = ComplexVariable(rho, zeros((2, 2), dtype="float64")) # rho = paddle.to_tensor(rho, zeros((2, 2), dtype="float64"))
basis0 = fluid.dygraph.to_variable(np.array([[1, 0], [0, 0]], dtype=np.complex128)) basis0 = paddle.to_tensor(np.array([[1, 0], [0, 0]], dtype=np.complex128))
basis1 = fluid.dygraph.to_variable(np.array([[0, 0], [0, 1]], dtype=np.complex128)) basis1 = paddle.to_tensor(np.array([[0, 0], [0, 1]], dtype=np.complex128))
rho0 = elementwise_mul(basis0, sin(theta[idx])) rho0 = multiply(basis0, sin(theta[idx]))
rho1 = elementwise_mul(basis1, cos(theta[idx])) rho1 = multiply(basis1, cos(theta[idx]))
rho = elementwise_add(rho0, rho1) rho = add(rho0, rho1)
op_list[i] = rho op_list[i] = rho
else: else:
print("cannot recognize the results_desired.") print("cannot recognize the result_desired.")
# rho = ComplexVariable(ones((2, 2), dtype="float64"), zeros((2, 2), dtype="float64")) # rho = paddle.to_tensor(ones((2, 2), dtype="float64"), zeros((2, 2), dtype="float64"))
measure_operator = fluid.dygraph.to_variable(op_list[0]) measure_operator = paddle.to_tensor(op_list[0])
if n > 1: if n > 1:
for idx in range(1, len(op_list)): for idx in range(1, len(op_list)):
measure_operator = kron(measure_operator, op_list[idx]) measure_operator = kron(measure_operator, op_list[idx])
state_measured = matmul(matmul(measure_operator, state), dagger(measure_operator)) state_measured = matmul(matmul(measure_operator, state), dagger(measure_operator))
prob = trace(matmul(matmul(dagger(measure_operator), measure_operator), state)).real prob = real(trace(matmul(matmul(dagger(measure_operator), measure_operator), state)))
state_measured = elementwise_div(state_measured, prob) state_measured = divide(state_measured, prob)
return state_measured, prob, result_desired return state_measured, prob, result_desired
def __measure_parameterless(self, state, which_qubits, result_desired): def __measure_parameterless(self, state, which_qubits, result_desired):
r"""进行 01 测量。 r"""进行 01 测量。
Args: Args:
state (ComplexVariable): 输入的量子态 state (Tensor): 输入的量子态
which_qubits (list): 测量作用的量子比特编号 which_qubits (list): 测量作用的量子比特编号
result_desired (list): 期望得到的测量结果,如 ``"0"``、``"1"`` 或者 ``["0", "1"]`` result_desired (str): 期望得到的测量结果
Returns: Returns:
ComplexVariable: 测量坍塌后的量子态 Tensor: 测量坍塌后的量子态
ComplexVariable:测量坍塌得到的概率 Tensor:测量坍塌得到的概率
list: 测量得到的结果(0 或 1) str: 测量得到的结果
""" """
n = self.get_qubit_number() n = self.get_qubit_number()
assert len(which_qubits) == len(result_desired), \ assert len(which_qubits) == len(result_desired), \
...@@ -732,22 +746,22 @@ class LoccNet(fluid.dygraph.Layer): ...@@ -732,22 +746,22 @@ class LoccNet(fluid.dygraph.Layer):
rho[int(k), int(k)] = 1 rho[int(k), int(k)] = 1
op_list[i] = rho op_list[i] = rho
if n > 1: if n > 1:
measure_operator = fluid.dygraph.to_variable(NKron(*op_list)) measure_operator = paddle.to_tensor(NKron(*op_list))
else: else:
measure_operator = fluid.dygraph.to_variable(op_list[0]) measure_operator = paddle.to_tensor(op_list[0])
state_measured = matmul(matmul(measure_operator, state), dagger(measure_operator)) state_measured = matmul(matmul(measure_operator, state), dagger(measure_operator))
prob = trace(matmul(matmul(dagger(measure_operator), measure_operator), state)).real prob = real(trace(matmul(matmul(dagger(measure_operator), measure_operator), state)))
state_measured = elementwise_div(state_measured, prob) state_measured = divide(state_measured, prob)
return state_measured, prob, result_desired return state_measured, prob, result_desired
def measure(self, status, which_qubits, results_desired, theta=None): def measure(self, status, which_qubits, results_desired, theta=None):
r"""对 LOCC 态节点进行 01 测量或者含参测量。 r"""对 LOCC 态节点进行 01 测量或者含参测量。
Args: Args:
state (LoccStatus or list): 输入的量子态,其类型应该为 ``LoccStatus`` 或者由其组成的 ``list`` status (LoccStatus or list): 输入的量子态,其类型应该为 ``LoccStatus`` 或者由其组成的 ``list``
which_qubits (tuple or list): 测量作用的量子比特编号,其形式为 ``(party_id, qubit_id)`` 的 ``tuple`` ,或者由其组成的 ``list`` which_qubits (tuple or list): 测量作用的量子比特编号,其形式为 ``(party_id, qubit_id)`` 的 ``tuple`` ,或者由其组成的 ``list``
result_desired (str or list): 期望得到的测量结果,用字符串进行表示,其类型为 ``str`` 或者由 ``str`` 组成的 ``list`` results_desired (str or list): 期望得到的测量结果,用字符串进行表示,其类型为 ``str`` 或者由 ``str`` 组成的 ``list``,如 ``"0"``、``"1"`` 或者 ``["0", "1"]``
theta (Variable): 测量运算的参数,默认是 ``None``,表示 01 测量;若要使用含参测量则需要赋值 theta (Tensor): 测量运算的参数,默认是 ``None``,表示 01 测量;若要使用含参测量则需要赋值
Returns: Returns:
LoccStatus or list: 测量后得到的 LOCC 态节点,其类型为 ``LoccStatus`` 或者由其组成的 ``list`` LoccStatus or list: 测量后得到的 LOCC 态节点,其类型为 ``LoccStatus`` 或者由其组成的 ``list``
......
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. # Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -34,7 +34,6 @@ probability and SINGLE is by the state collapse method. Former is significant fa ...@@ -34,7 +34,6 @@ probability and SINGLE is by the state collapse method. Former is significant fa
import numpy as np import numpy as np
import paddle import paddle
import paddle.fluid
import gc import gc
from collections import Counter from collections import Counter
import copy import copy
...@@ -43,72 +42,70 @@ from enum import Enum ...@@ -43,72 +42,70 @@ from enum import Enum
import random import random
### InitPorcess ### # InitProcess
def init_state_10(n): def init_state_10(n):
""" """
Generate state with n qubits Generate state with n qubits
:param n: number of qubits :param n: number of qubits
:return: tensor of state :return: tensor of state
""" """
re1 = paddle.fluid.layers.ones([1], 'float64') state1 = paddle.ones([1], 'float64')
re0 = paddle.fluid.layers.zeros([2 ** n - 1], 'float64') state0 = paddle.zeros([2 ** n - 1], 'float64')
re = paddle.fluid.layers.concat([re1, re0]) state = paddle.concat([state1, state0])
del re1, re0 del state1, state0
gc.collect() # free the intermediate big data immediately gc.collect() # free the intermediate big data immediately
im = paddle.fluid.layers.zeros([2 ** n], 'float64') state = paddle.cast(state, 'complex128')
state = paddle.fluid.ComplexVariable(re, im)
del re, im
gc.collect() # free the intermediate big data immediately gc.collect() # free the intermediate big data immediately
# print(state.numpy())
return state return state
def init_state_gen(n, i = 0): def init_state_gen(n, i=0):
""" """
Generate state with n qubits Generate state with n qubits
:param n: number of qubits :param n: number of qubits
:param i: the ith vector in computational basis :param i: the ith vector in computational basis
:return: tensor of state :return: tensor of state
""" """
assert 0 <= i < 2**n, 'Invalid index' assert 0 <= i < 2 ** n, 'Invalid index'
if n == 1: if n == 1:
re1 = paddle.fluid.layers.ones([1], 'float64') state1 = paddle.ones([1], 'float64')
re0 = paddle.fluid.layers.zeros([2 ** n - 1], 'float64') state0 = paddle.zeros([2 ** n - 1], 'float64')
if i == 0: if i == 0:
re = paddle.fluid.layers.concat([re1, re0]) state = paddle.concat([state1, state0])
else: else:
re = paddle.fluid.layers.concat([re0, re1]) state = paddle.concat([state0, state1])
im = paddle.fluid.layers.zeros([2 ** n], 'float64')
state = paddle.fluid.ComplexVariable(re, im)
else: else:
if i == 0: if i == 0:
re1 = paddle.fluid.layers.ones([1], 'float64') state1 = paddle.ones([1], 'float64')
re0 = paddle.fluid.layers.zeros([2 ** n - 1], 'float64') state0 = paddle.zeros([2 ** n - 1], 'float64')
re = paddle.fluid.layers.concat([re1, re0]) state = paddle.concat([state1, state0])
elif i == 2 ** n - 1: elif i == 2 ** n - 1:
re1 = paddle.fluid.layers.ones([1], 'float64') state1 = paddle.ones([1], 'float64')
re0 = paddle.fluid.layers.zeros([2 ** n - 1], 'float64') state0 = paddle.zeros([2 ** n - 1], 'float64')
re = paddle.fluid.layers.concat([re0, re1]) state = paddle.concat([state0, state1])
else: else:
re1 = paddle.fluid.layers.ones([1], 'float64') state1 = paddle.ones([1], 'float64')
re0 = paddle.fluid.layers.zeros([i], 'float64') state0 = paddle.zeros([i], 'float64')
re00 = paddle.fluid.layers.zeros([2 ** n - i - 1], 'float64') state00 = paddle.zeros([2 ** n - i - 1], 'float64')
re = paddle.fluid.layers.concat([re0, re1, re00]) state = paddle.concat([state0, state1, state00])
del re1, re0 del state1, state0
gc.collect() # free the intermediate big data immediately try:
im = paddle.fluid.layers.zeros([2 ** n], 'float64') del state00
state = paddle.fluid.ComplexVariable(re, im) except NameError:
del re, im pass
gc.collect() # free the intermediate big data immediately gc.collect() # free the intermediate big data immediately
return state
state = paddle.cast(state, 'complex128')
gc.collect() # free the intermediate big data immediately
return state
### DEFINE_GATE ### # Define gate
def x_gate_matrix(): def x_gate_matrix():
""" """
Pauli x Pauli x
...@@ -154,20 +151,22 @@ def u_gate_matrix(params): ...@@ -154,20 +151,22 @@ def u_gate_matrix(params):
""" """
theta, phi, lam = params theta, phi, lam = params
if (type(theta) is paddle.fluid.core_avx.VarBase and if (type(theta) is paddle.Tensor and
type(phi) is paddle.fluid.core_avx.VarBase and type(phi) is paddle.Tensor and
type(lam) is paddle.fluid.core_avx.VarBase): type(lam) is paddle.Tensor):
re_a = paddle.fluid.layers.cos(theta / 2) re_a = paddle.cos(theta / 2)
re_b = - paddle.fluid.layers.cos(lam) * paddle.fluid.layers.sin(theta / 2) re_b = - paddle.cos(lam) * paddle.sin(theta / 2)
re_c = paddle.fluid.layers.cos(phi) * paddle.fluid.layers.sin(theta / 2) re_c = paddle.cos(phi) * paddle.sin(theta / 2)
re_d = paddle.fluid.layers.cos(phi + lam) * paddle.fluid.layers.cos(theta / 2) re_d = paddle.cos(phi + lam) * paddle.cos(theta / 2)
im_a = paddle.fluid.layers.zeros([1], 'float64') im_a = paddle.zeros([1], 'float64')
im_b = - paddle.fluid.layers.sin(lam) * paddle.fluid.layers.sin(theta / 2) im_b = - paddle.sin(lam) * paddle.sin(theta / 2)
im_c = paddle.fluid.layers.sin(phi) * paddle.fluid.layers.sin(theta / 2) im_c = paddle.sin(phi) * paddle.sin(theta / 2)
im_d = paddle.fluid.layers.sin(phi + lam) * paddle.fluid.layers.cos(theta / 2) im_d = paddle.sin(phi + lam) * paddle.cos(theta / 2)
re = paddle.fluid.layers.reshape(paddle.fluid.layers.concat([re_a, re_b, re_c, re_d]), [2, 2])
im = paddle.fluid.layers.reshape(paddle.fluid.layers.concat([im_a, im_b, im_c, im_d]), [2, 2]) re = paddle.reshape(paddle.concat([re_a, re_b, re_c, re_d]), [2, 2])
return paddle.fluid.framework.ComplexVariable(re, im) im = paddle.reshape(paddle.concat([im_a, im_b, im_c, im_d]), [2, 2])
return re + im * paddle.to_tensor([1j], 'complex128')
elif (type(theta) is float and elif (type(theta) is float and
type(phi) is float and type(phi) is float and
type(lam) is float): type(lam) is float):
...@@ -182,11 +181,10 @@ def u_gate_matrix(params): ...@@ -182,11 +181,10 @@ def u_gate_matrix(params):
# compare the paddle and np version, they should be equal # compare the paddle and np version, they should be equal
# a = u_gate_matrix([1.0, 2.0, 3.0]) # a = u_gate_matrix([1.0, 2.0, 3.0])
# print(a) # print(a)
# with paddle.fluid.dygraph.guard(): # a = u_gate_matrix([paddle.to_tensor(np.array([1.0])),
# a = u_gate_matrix([paddle.fluid.dygraph.to_variable(np.array([1.0])), # paddle.to_tensor(np.array([2.0])),
# paddle.fluid.dygraph.to_variable(np.array([2.0])), # paddle.to_tensor(np.array([3.0]))])
# paddle.fluid.dygraph.to_variable(np.array([3.0]))]) # print(a.numpy())
# print(a.numpy())
def cx_gate_matrix(): def cx_gate_matrix():
...@@ -197,7 +195,8 @@ def cx_gate_matrix(): ...@@ -197,7 +195,8 @@ def cx_gate_matrix():
return np.array([[1, 0, 0, 0], return np.array([[1, 0, 0, 0],
[0, 1, 0, 0], [0, 1, 0, 0],
[0, 0, 0, 1], [0, 0, 0, 1],
[0, 0, 1, 0]], dtype=complex).reshape(2, 2, 2, 2) [0, 0, 1, 0]], dtype=complex).reshape((2, 2, 2, 2))
def swap_gate_matrix(): def swap_gate_matrix():
""" """
...@@ -210,7 +209,7 @@ def swap_gate_matrix(): ...@@ -210,7 +209,7 @@ def swap_gate_matrix():
[0, 0, 0, 1]], dtype=complex).reshape(2, 2, 2, 2) [0, 0, 0, 1]], dtype=complex).reshape(2, 2, 2, 2)
### PaddleE ### # PaddleE
def normalize_axis(axis, ndim): def normalize_axis(axis, ndim):
if axis < 0: if axis < 0:
axis += ndim axis += ndim
...@@ -261,7 +260,7 @@ def moveaxis(m, source, destination): ...@@ -261,7 +260,7 @@ def moveaxis(m, source, destination):
for dest, src in sorted(zip(destination, source)): for dest, src in sorted(zip(destination, source)):
order.insert(dest, src) order.insert(dest, src)
result = paddle.fluid.layers.transpose(m, order) result = paddle.transpose(m, order)
return result return result
...@@ -284,25 +283,26 @@ def complex_moveaxis(m, source, destination): ...@@ -284,25 +283,26 @@ def complex_moveaxis(m, source, destination):
for dest, src in sorted(zip(destination, source)): for dest, src in sorted(zip(destination, source)):
order.insert(dest, src) order.insert(dest, src)
result = paddle.complex.transpose(m, order) result = paddle.transpose(m, order)
return result return result
def complex_abs(m): # def complex_abs(m):
# check1 = np.abs(m.numpy()) # # check1 = np.abs(m.numpy())
#
re = paddle.fluid.layers.elementwise_mul(m.real, m.real) # re = paddle.multiply(paddle.real(m), paddle.real(m))
im = paddle.fluid.layers.elementwise_mul(m.imag, m.imag) # im = paddle.multiply(paddle.imag(m), paddle.imag(m))
m = paddle.fluid.layers.elementwise_add(re, im) # m = paddle.add(re, im)
m = paddle.fluid.layers.sqrt(m) # m = paddle.fluid.layers.elementwise_pow(m, paddle.fluid.layers.ones_like(m) * 0.5) # m = paddle.sqrt(m)
# # m = paddle.pow(m, paddle.ones_like(m) * 0.5)
# check2 = m.numpy() #
# assert (check1 == check2).all() # # check2 = m.numpy()
# # assert (check1 == check2).all()
return m #
# return m
### TransferProcess ### # TransferProcess
def transfer_state(state, gate_matrix, bits): def transfer_state(state, gate_matrix, bits):
""" """
Transfer to the next state Transfer to the next state
...@@ -312,9 +312,10 @@ def transfer_state(state, gate_matrix, bits): ...@@ -312,9 +312,10 @@ def transfer_state(state, gate_matrix, bits):
:return: :return:
""" """
assert type(gate_matrix) is np.ndarray or type(gate_matrix) is paddle.fluid.framework.ComplexVariable assert (type(gate_matrix) is np.ndarray) or \
(type(gate_matrix) is paddle.Tensor and gate_matrix.dtype.name == "COMPLEX128")
assert type(state) is paddle.fluid.ComplexVariable and len(state.shape) == 1 assert type(state) is paddle.Tensor and state.dtype.name == "COMPLEX128" and len(state.shape) == 1
# calc source_pos target_pos # calc source_pos target_pos
n = int(np.log2(state.shape[0])) n = int(np.log2(state.shape[0]))
source_pos = copy.deepcopy(bits) # copy bits, it should NOT change the order of bits source_pos = copy.deepcopy(bits) # copy bits, it should NOT change the order of bits
...@@ -323,8 +324,8 @@ def transfer_state(state, gate_matrix, bits): ...@@ -323,8 +324,8 @@ def transfer_state(state, gate_matrix, bits):
target_pos = list(range(len(bits))) target_pos = list(range(len(bits)))
# ### check # ### check
# state_check = transfer_state(paddle.complex.reshape(state, [2] * n), gate_matrix, bits) # state_check = transfer_state(paddle.reshape(state, [2] * n), gate_matrix, bits)
# state_check = paddle.complex.reshape(state_check, [2 ** n]) # state_check = paddle.reshape(state_check, [2 ** n])
# compressed moveaxis # compressed moveaxis
# compress the continuous dim before moveaxis # compress the continuous dim before moveaxis
...@@ -346,31 +347,31 @@ def transfer_state(state, gate_matrix, bits): ...@@ -346,31 +347,31 @@ def transfer_state(state, gate_matrix, bits):
# print('->') # print('->')
# print(compressed_shape) # print(compressed_shape)
# print(compressed_source_pos) # always [1], [1, 3], or [3, 1] # print(compressed_source_pos) # always [1], [1, 3], or [3, 1]
state = paddle.complex.reshape(state, compressed_shape_before_moveaxis) state = paddle.reshape(state, compressed_shape_before_moveaxis)
state = complex_moveaxis(state, compressed_source_pos, target_pos) state = complex_moveaxis(state, compressed_source_pos, target_pos)
compressed_shape_after_moveaxis = state.shape compressed_shape_after_moveaxis = state.shape
# reshape # reshape
state_new_shape = [2 ** len(bits), 2 ** (n - len(bits))] state_new_shape = [2 ** len(bits), 2 ** (n - len(bits))]
state = paddle.complex.reshape(state, state_new_shape) state = paddle.reshape(state, state_new_shape)
# gate_matrix # gate_matrix
if type(gate_matrix) is np.ndarray: if type(gate_matrix) is np.ndarray:
gate_new_shape = [2 ** (len(gate_matrix.shape) - len(bits)), 2 ** len(bits)] gate_new_shape = [2 ** (len(gate_matrix.shape) - len(bits)), 2 ** len(bits)]
gate_matrix = gate_matrix.reshape(gate_new_shape) gate_matrix = gate_matrix.reshape(gate_new_shape)
gate_matrix = paddle.fluid.dygraph.to_variable(gate_matrix) gate_matrix = paddle.to_tensor(gate_matrix)
elif type(gate_matrix) is paddle.fluid.framework.ComplexVariable: elif type(gate_matrix) is paddle.Tensor and gate_matrix.dtype.name == "COMPLEX128":
pass pass
else: else:
assert False assert False
# matmul # matmul
state = paddle.complex.matmul(gate_matrix, state) state = paddle.matmul(gate_matrix, state)
# restore compressed moveaxis reshape # restore compressed moveaxis reshape
state = paddle.complex.reshape(state, compressed_shape_after_moveaxis) state = paddle.reshape(state, compressed_shape_after_moveaxis)
state = complex_moveaxis(state, target_pos, compressed_source_pos) state = complex_moveaxis(state, target_pos, compressed_source_pos)
state = paddle.complex.reshape(state, [2 ** n]) state = paddle.reshape(state, [2 ** n])
# ### check # ### check
# assert (np.all(state.numpy() == state_check.numpy())) # assert (np.all(state.numpy() == state_check.numpy()))
...@@ -378,8 +379,8 @@ def transfer_state(state, gate_matrix, bits): ...@@ -378,8 +379,8 @@ def transfer_state(state, gate_matrix, bits):
return state return state
### StateTranfer ### # StateTransfer
def StateTranfer(state, gate_name, bits, params=None): def StateTransfer(state, gate_name, bits, params=None):
""" """
To transfer state by only gate name and bits To transfer state by only gate name and bits
:param state: the last step state, can be init vector or the last step vector. :param state: the last step state, can be init vector or the last step vector.
...@@ -416,7 +417,7 @@ def StateTranfer(state, gate_name, bits, params=None): ...@@ -416,7 +417,7 @@ def StateTranfer(state, gate_name, bits, params=None):
return state return state
### MeasureProcess ### # MeasureProcess
class MEAS_METHOD(Enum): class MEAS_METHOD(Enum):
""" """
To control the measure method To control the measure method
...@@ -483,7 +484,7 @@ def measure_all(state): ...@@ -483,7 +484,7 @@ def measure_all(state):
outs = '' outs = ''
for i in range(n): for i in range(n):
out, state = measure_single(state, i) # measure qubit0 will collapse it out, state = measure_single(state, i) # measure qubit0 will collapse it
outs = str(out) + outs # from low to high position outs = str(out) + outs # from low to high position
return outs return outs
...@@ -513,10 +514,10 @@ def measure_by_probability(state, times): ...@@ -513,10 +514,10 @@ def measure_by_probability(state, times):
""" """
# print("Measure method Probability") # print("Measure method Probability")
assert type(state) is paddle.fluid.ComplexVariable and len(state.shape) == 1 assert type(state) is paddle.Tensor and state.dtype.name == "COMPLEX128" and len(state.shape) == 1
n = int(np.log2(state.shape[0])) n = int(np.log2(state.shape[0]))
prob_array = complex_abs(state) # complex -> real prob_array = paddle.abs(state) # complex -> real
prob_array = paddle.fluid.layers.elementwise_mul(prob_array, prob_array) prob_array = paddle.multiply(prob_array, prob_array)
prob_array = prob_array.numpy() prob_array = prob_array.numpy()
gc.collect() gc.collect()
...@@ -536,11 +537,11 @@ def measure_by_probability(state, times): ...@@ -536,11 +537,11 @@ def measure_by_probability(state, times):
samples = np.random.choice(range(2 ** n), times, p=prob_array) samples = np.random.choice(range(2 ** n), times, p=prob_array)
count_samples = Counter(samples) count_samples = Counter(samples)
result = {} result = {}
for idex in count_samples: for idx in count_samples:
""" """
result[prob_key[idex]] = count_samples[idex] result[prob_key[idx]] = count_samples[idx]
""" """
result[oct_to_bin_str(idex, n)] = count_samples[idex] result[oct_to_bin_str(idx, n)] = count_samples[idx]
return result return result
...@@ -559,7 +560,7 @@ def measure_state(state, shots): ...@@ -559,7 +560,7 @@ def measure_state(state, shots):
raise Exception("Measure Error") raise Exception("Measure Error")
### RandomCircuit ### # RandomCircuit
def GenerateRandomCirc(state, circ_depth, n): def GenerateRandomCirc(state, circ_depth, n):
""" """
Generate random circ Generate random circ
...@@ -576,7 +577,7 @@ def GenerateRandomCirc(state, circ_depth, n): ...@@ -576,7 +577,7 @@ def GenerateRandomCirc(state, circ_depth, n):
rand_gate_bits = random.sample(range(n), 2) rand_gate_bits = random.sample(range(n), 2)
else: else:
rand_gate_bits = random.sample(range(n), 1) rand_gate_bits = random.sample(range(n), 1)
internal_state = StateTranfer(internal_state, gate_string[rand_gate_pos], rand_gate_bits) internal_state = StateTransfer(internal_state, gate_string[rand_gate_pos], rand_gate_bits)
state = internal_state state = internal_state
return state return state
...@@ -603,19 +604,19 @@ def GenerateRandomCircAndRev(state, circ_depth, n): ...@@ -603,19 +604,19 @@ def GenerateRandomCircAndRev(state, circ_depth, n):
rand_gate_pos_all.append(rand_gate_pos) rand_gate_pos_all.append(rand_gate_pos)
rand_gate_bits_all.append(rand_gate_bits) rand_gate_bits_all.append(rand_gate_bits)
internal_state = StateTranfer(internal_state, gate_string[rand_gate_pos], rand_gate_bits) internal_state = StateTransfer(internal_state, gate_string[rand_gate_pos], rand_gate_bits)
rand_gate_pos_all = list(reversed(rand_gate_pos_all)) rand_gate_pos_all = list(reversed(rand_gate_pos_all))
rand_gate_bits_all = list(reversed(rand_gate_bits_all)) rand_gate_bits_all = list(reversed(rand_gate_bits_all))
for idex, item in enumerate(rand_gate_pos_all): for idex, item in enumerate(rand_gate_pos_all):
internal_state = StateTranfer(internal_state, gate_string[item], rand_gate_bits_all[idex]) internal_state = StateTransfer(internal_state, gate_string[item], rand_gate_bits_all[idex])
state = internal_state state = internal_state
return state return state
### Tester ### # Tester
def RandomTestIt(bits_num, circ_num): def RandomTestIt(bits_num, circ_num):
""" """
Random Check Random Check
...@@ -645,9 +646,9 @@ def Test_x_h_CNOT(): # 3 bits coverage test ...@@ -645,9 +646,9 @@ def Test_x_h_CNOT(): # 3 bits coverage test
""" """
state = init_state_10(3) state = init_state_10(3)
state = StateTranfer(state, 'x', [0]) state = StateTransfer(state, 'x', [0])
state = StateTranfer(state, 'h', [1]) state = StateTransfer(state, 'h', [1])
state = StateTranfer(state, 'CNOT', [1, 2]) state = StateTransfer(state, 'CNOT', [1, 2])
re = measure_state(state, 2 ** 10) re = measure_state(state, 2 ** 10)
# print(re) # print(re)
assert ('001' in list(re.keys()) and '111' in list(re.keys())) assert ('001' in list(re.keys()) and '111' in list(re.keys()))
...@@ -662,14 +663,14 @@ def Test_cnot_1(): ...@@ -662,14 +663,14 @@ def Test_cnot_1():
""" """
state = init_state_10(3) state = init_state_10(3)
state = StateTranfer(state, 'h', [0]) state = StateTransfer(state, 'h', [0])
state = StateTranfer(state, 'CNOT', [0, 1]) state = StateTransfer(state, 'CNOT', [0, 1])
state = StateTranfer(state, 'CNOT', [0, 2]) state = StateTransfer(state, 'CNOT', [0, 2])
state = StateTranfer(state, 'CNOT', [1, 2]) state = StateTransfer(state, 'CNOT', [1, 2])
state = StateTranfer(state, 'CNOT', [1, 2]) state = StateTransfer(state, 'CNOT', [1, 2])
state = StateTranfer(state, 'CNOT', [0, 2]) state = StateTransfer(state, 'CNOT', [0, 2])
state = StateTranfer(state, 'CNOT', [0, 1]) state = StateTransfer(state, 'CNOT', [0, 1])
state = StateTranfer(state, 'h', [0]) state = StateTransfer(state, 'h', [0])
re = measure_state(state, 2 ** 10) re = measure_state(state, 2 ** 10)
assert ('000' in list(re.keys())) assert ('000' in list(re.keys()))
assert (2 ** 10 in list(re.values())) assert (2 ** 10 in list(re.values()))
...@@ -683,14 +684,14 @@ def Test_cnot_2(): ...@@ -683,14 +684,14 @@ def Test_cnot_2():
""" """
state = init_state_10(3) state = init_state_10(3)
state = StateTranfer(state, 'h', [2]) state = StateTransfer(state, 'h', [2])
state = StateTranfer(state, 'CNOT', [2, 1]) state = StateTransfer(state, 'CNOT', [2, 1])
state = StateTranfer(state, 'CNOT', [2, 0]) state = StateTransfer(state, 'CNOT', [2, 0])
state = StateTranfer(state, 'CNOT', [1, 0]) state = StateTransfer(state, 'CNOT', [1, 0])
state = StateTranfer(state, 'CNOT', [1, 0]) state = StateTransfer(state, 'CNOT', [1, 0])
state = StateTranfer(state, 'CNOT', [2, 0]) state = StateTransfer(state, 'CNOT', [2, 0])
state = StateTranfer(state, 'CNOT', [2, 1]) state = StateTransfer(state, 'CNOT', [2, 1])
state = StateTranfer(state, 'h', [2]) state = StateTransfer(state, 'h', [2])
re = measure_state(state, 2 ** 10) re = measure_state(state, 2 ** 10)
assert ('000' in list(re.keys())) assert ('000' in list(re.keys()))
assert (2 ** 10 in list(re.values())) assert (2 ** 10 in list(re.values()))
...@@ -705,7 +706,7 @@ def Test3All(): ...@@ -705,7 +706,7 @@ def Test3All():
return Test_x_h_CNOT() and Test_cnot_1() and Test_cnot_2() return Test_x_h_CNOT() and Test_cnot_1() and Test_cnot_2()
### Sim2Main ### # Sim2Main
def main(bits_num=None, circ_num=None): def main(bits_num=None, circ_num=None):
""" """
:param bits_num: the number of qubits :param bits_num: the number of qubits
...@@ -727,18 +728,18 @@ def main(bits_num=None, circ_num=None): ...@@ -727,18 +728,18 @@ def main(bits_num=None, circ_num=None):
state = init_state_10(bits_num) state = init_state_10(bits_num)
# ------------------tik------- # ------------------tik-------
# state = StateTranfer(state, 'h', [0]) # state = StateTransfer(state, 'h', [0])
# state = StateTranfer(state, 'x', [1]) # state = StateTransfer(state, 'x', [1])
# state = StateTranfer(state, 'x', [2]) # state = StateTransfer(state, 'x', [2])
# state = StateTranfer(state, 'u', [3], [0.3, 0.5, 0.7]) # state = StateTransfer(state, 'u', [3], [0.3, 0.5, 0.7])
# state = StateTranfer(state, 'CNOT', [0, 1]) # state = StateTransfer(state, 'CNOT', [0, 1])
# state = StateTranfer(state, 'CNOT', [2, 1]) # state = StateTransfer(state, 'CNOT', [2, 1])
# -----------------tok--------- # -----------------tok---------
# ------------------tik------- # ------------------tik-------
state = StateTranfer(state, 'x', [0]) state = StateTransfer(state, 'x', [0])
state = StateTranfer(state, 'h', [1]) state = StateTransfer(state, 'h', [1])
#state = StateTranfer(state, 'CNOT', [0, 1]) # state = StateTransfer(state, 'CNOT', [0, 1])
# -----------------tok--------- # -----------------tok---------
# ------------------tik------- # ------------------tik-------
...@@ -767,11 +768,11 @@ def Tester(bits_num=None, circ_num=None): ...@@ -767,11 +768,11 @@ def Tester(bits_num=None, circ_num=None):
if __name__ == '__main__': if __name__ == '__main__':
with paddle.fluid.dygraph.guard(): paddle.set_device('cpu')
# main(bits_num=5, circ_num=50) # main(bits_num=5, circ_num=50)
main(bits_num=5) main(bits_num=5)
# RandomTestIt(bits_num=5, circ_num=50) # RandomTestIt(bits_num=5, circ_num=50)
# print(Test3All()) # print(Test3All())
# print(Tester(bits_num=5, circ_num=50)) # print(Tester(bits_num=5, circ_num=50))
#Tester(bits_num=6, circ_num=100) # Tester(bits_num=6, circ_num=100)
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. # Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -296,8 +296,8 @@ def bell_diagonal_state(p1, p2, p3, p4): ...@@ -296,8 +296,8 @@ def bell_diagonal_state(p1, p2, p3, p4):
[0. +0.j 0. +0.j 0.25+0.j 0. +0.j] [0. +0.j 0. +0.j 0.25+0.j 0. +0.j]
[0. +0.j 0. +0.j 0. +0.j 0.25+0.j]] [0. +0.j 0. +0.j 0. +0.j 0.25+0.j]]
""" """
# p4 = 1 - p1 - p2 - p3 assert 0 <= p1 <= 1 and 0 <= p2 <= 1 and 0 <= p3 <= 1 and 0 <= p4 <= 1, "Each probability must be in [0, 1]"
# assert 0 <= p1 <= 1 and 0 <= p2 <= 1 and 0 <= p3 <= 1 and 0 <= p4 <= 1, "Probability must be in [0, 1]" assert abs(p1 + p2 + p3 + p4 - 1) < 1e-6, "The sum of probabilities should be 1"
coeff = np.sqrt(0.5) coeff = np.sqrt(0.5)
phi_p_vec = np.array([[coeff, 0, 0, coeff]]) phi_p_vec = np.array([[coeff, 0, 0, coeff]])
......
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. # Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
from functools import reduce from functools import reduce
import numpy import numpy as np
from numpy import absolute, log from numpy import absolute, log
from numpy import diag, dot, identity from numpy import diag, dot, identity
from numpy import kron as np_kron from numpy import kron as np_kron
...@@ -26,18 +26,18 @@ from numpy import sum as np_sum ...@@ -26,18 +26,18 @@ from numpy import sum as np_sum
from numpy import transpose as np_transpose from numpy import transpose as np_transpose
from numpy import zeros as np_zeros from numpy import zeros as np_zeros
from paddle.complex import elementwise_add from paddle import add, to_tensor
from paddle.complex import kron as pp_kron from paddle import kron as pp_kron
from paddle.complex import matmul from paddle import matmul
from paddle.complex import transpose as pp_transpose from paddle import transpose as pp_transpose
from paddle.fluid.dygraph import to_variable from paddle import concat, cos, ones, reshape, sin
from paddle.fluid.framework import ComplexVariable from paddle import zeros as pp_zeros
from paddle.fluid.layers import concat, cos, ones, reshape, sin
from paddle.fluid.layers import zeros as pp_zeros
from scipy.linalg import logm, sqrtm from scipy.linalg import logm, sqrtm
import paddle
__all__ = [ __all__ = [
"partial_trace", "partial_trace",
"state_fidelity", "state_fidelity",
...@@ -61,43 +61,40 @@ def partial_trace(rho_AB, dim1, dim2, A_or_B): ...@@ -61,43 +61,40 @@ def partial_trace(rho_AB, dim1, dim2, A_or_B):
r"""计算量子态的偏迹。 r"""计算量子态的偏迹。
Args: Args:
rho_AB (ComplexVariable): 输入的量子态 rho_AB (Tensor): 输入的量子态
dim1 (int): 系统A的维数 dim1 (int): 系统A的维数
dim2 (int): 系统B的维数 dim2 (int): 系统B的维数
A_or_B (int): 1或者2,1表示计算系统A上的偏迹,2表示计算系统B上的偏迹 A_or_B (int): 1或者2,1表示计算系统A上的偏迹,2表示计算系统B上的偏迹
Returns: Returns:
ComplexVariable: 输入的量子态的偏迹 Tensor: 输入的量子态的偏迹
""" """
if A_or_B == 2: if A_or_B == 2:
dim1, dim2 = dim2, dim1 dim1, dim2 = dim2, dim1
idty_np = identity(dim2).astype("complex128") idty_np = identity(dim2).astype("complex128")
idty_B = to_variable(idty_np) idty_B = to_tensor(idty_np)
zero_np = np_zeros([dim2, dim2], "complex128") zero_np = np_zeros([dim2, dim2], "complex128")
res = to_variable(zero_np) res = to_tensor(zero_np)
for dim_j in range(dim1): for dim_j in range(dim1):
row_top = pp_zeros([1, dim_j], dtype="float64") row_top = pp_zeros([1, dim_j], dtype="float64")
row_mid = ones([1, 1], dtype="float64") row_mid = ones([1, 1], dtype="float64")
row_bot = pp_zeros([1, dim1 - dim_j - 1], dtype="float64") row_bot = pp_zeros([1, dim1 - dim_j - 1], dtype="float64")
bra_j_re = concat([row_top, row_mid, row_bot], axis=1) bra_j = concat([row_top, row_mid, row_bot], axis=1)
bra_j_im = pp_zeros([1, dim1], dtype="float64") bra_j = paddle.cast(bra_j, 'complex128')
bra_j = ComplexVariable(bra_j_re, bra_j_im)
if A_or_B == 1: if A_or_B == 1:
row_tmp = pp_kron(bra_j, idty_B) row_tmp = pp_kron(bra_j, idty_B)
res = elementwise_add(res, matmul(matmul(row_tmp, rho_AB), row_tmp_conj = paddle.conj(row_tmp)
pp_transpose(ComplexVariable(row_tmp.real, -row_tmp.imag), res = add(res, matmul(matmul(row_tmp, rho_AB), pp_transpose(row_tmp_conj, perm=[1, 0]), ), )
perm=[1, 0]), ), )
if A_or_B == 2: if A_or_B == 2:
row_tmp = pp_kron(idty_B, bra_j) row_tmp = pp_kron(idty_B, bra_j)
res = elementwise_add(res, matmul(matmul(row_tmp, rho_AB), row_tmp_conj = paddle.conj(row_tmp)
pp_transpose(ComplexVariable(row_tmp.real, -row_tmp.imag), res = add(res, matmul(matmul(row_tmp, rho_AB), pp_transpose(row_tmp_conj, perm=[1, 0]), ), )
perm=[1, 0]), ), )
return res return res
...@@ -116,7 +113,7 @@ def state_fidelity(rho, sigma): ...@@ -116,7 +113,7 @@ def state_fidelity(rho, sigma):
float: 输入的量子态之间的保真度 float: 输入的量子态之间的保真度
""" """
assert rho.shape == sigma.shape, 'The shape of two quantum states are different' assert rho.shape == sigma.shape, 'The shape of two quantum states are different'
fidelity = numpy.trace(sqrtm(sqrtm(rho) @ sigma @ sqrtm(rho))).real fidelity = np.trace(sqrtm(sqrtm(rho) @ sigma @ sqrtm(rho))).real
return fidelity return fidelity
...@@ -196,7 +193,7 @@ def relative_entropy(rho, sig): ...@@ -196,7 +193,7 @@ def relative_entropy(rho, sig):
float: 输入的量子态之间的相对熵 float: 输入的量子态之间的相对熵
""" """
assert rho.shape == sig.shape, 'The shape of two quantum states are different' assert rho.shape == sig.shape, 'The shape of two quantum states are different'
res = numpy.trace(rho @ logm(rho) - rho @ logm(sig)) res = np.trace(rho @ logm(rho) - rho @ logm(sig))
return res.real return res.real
...@@ -209,7 +206,7 @@ def NKron(matrix_A, matrix_B, *args): ...@@ -209,7 +206,7 @@ def NKron(matrix_A, matrix_B, *args):
*args (numpy.ndarray): 其余矩阵 *args (numpy.ndarray): 其余矩阵
Returns: Returns:
ComplexVariable: 输入矩阵的Kronecker积 Tensor: 输入矩阵的Kronecker积
.. code-block:: python .. code-block:: python
...@@ -229,28 +226,27 @@ def dagger(matrix): ...@@ -229,28 +226,27 @@ def dagger(matrix):
r"""计算矩阵的埃尔米特转置,即Hermitian transpose。 r"""计算矩阵的埃尔米特转置,即Hermitian transpose。
Args: Args:
matrix (ComplexVariable): 需要埃尔米特转置的矩阵 matrix (Tensor): 需要埃尔米特转置的矩阵
Returns: Returns:
ComplexVariable: 输入矩阵的埃尔米特转置 Tensor: 输入矩阵的埃尔米特转置
代码示例: 代码示例:
.. code-block:: python .. code-block:: python
from paddle_quantum.utils import dagger from paddle_quantum.utils import dagger
from paddle import fluid
import numpy as np import numpy as np
with fluid.dygraph.guard(): rho = paddle.to_tensor(np.array([[1+1j, 2+2j], [3+3j, 4+4j]]))
rho = fluid.dygraph.to_variable(np.array([[1+1j, 2+2j], [3+3j, 4+4j]])) print(dagger(rho).numpy())
print(dagger(rho).numpy())
:: ::
[[1.-1.j 3.-3.j] [[1.-1.j 3.-3.j]
[2.-2.j 4.-4.j]] [2.-2.j 4.-4.j]]
""" """
matrix_dagger = pp_transpose(ComplexVariable(matrix.real, -matrix.imag), perm=[1, 0]) matrix_conj = paddle.conj(matrix)
matrix_dagger = pp_transpose(matrix_conj, perm=[1, 0])
return matrix_dagger return matrix_dagger
...@@ -294,8 +290,8 @@ def pauli_str_to_matrix(pauli_str, n): ...@@ -294,8 +290,8 @@ def pauli_str_to_matrix(pauli_str, n):
Returns: Returns:
numpy.ndarray: 输入列表对应的可观测量的矩阵形式 numpy.ndarray: 输入列表对应的可观测量的矩阵形式
""" """
pauli_dict = {'i': numpy.eye(2) + 0j, 'x': numpy.array([[0, 1], [1, 0]]) + 0j, pauli_dict = {'i': np.eye(2) + 0j, 'x': np.array([[0, 1], [1, 0]]) + 0j,
'y': numpy.array([[0, -1j], [1j, 0]]), 'z': numpy.array([[1, 0], [0, -1]]) + 0j} 'y': np.array([[0, -1j], [1j, 0]]), 'z': np.array([[1, 0], [0, -1]]) + 0j}
# Parse pauli_str; 'x0,z1,y4' to 'xziiy' # Parse pauli_str; 'x0,z1,y4' to 'xziiy'
new_pauli_str = [] new_pauli_str = []
...@@ -321,6 +317,7 @@ def pauli_str_to_matrix(pauli_str, n): ...@@ -321,6 +317,7 @@ def pauli_str_to_matrix(pauli_str, n):
return sum(matrices) return sum(matrices)
def partial_transpose_2(density_op, sub_system=None): def partial_transpose_2(density_op, sub_system=None):
r"""计算输入量子态的 partial transpose :math:`\rho^{T_A}` r"""计算输入量子态的 partial transpose :math:`\rho^{T_A}`
...@@ -349,7 +346,7 @@ def partial_transpose_2(density_op, sub_system=None): ...@@ -349,7 +346,7 @@ def partial_transpose_2(density_op, sub_system=None):
sys_idx = 2 if sub_system is None else 1 sys_idx = 2 if sub_system is None else 1
# Copy the density matrix and not corrupt the original one # Copy the density matrix and not corrupt the original one
transposed_density_op = numpy.copy(density_op) transposed_density_op = np.copy(density_op)
if sys_idx == 2: if sys_idx == 2:
for j in [0, 2]: for j in [0, 2]:
for i in [0, 2]: for i in [0, 2]:
...@@ -372,13 +369,14 @@ def partial_transpose(density_op, n): ...@@ -372,13 +369,14 @@ def partial_transpose(density_op, n):
""" """
# Copy the density matrix and not corrupt the original one # Copy the density matrix and not corrupt the original one
transposed_density_op = numpy.copy(density_op) transposed_density_op = np.copy(density_op)
for j in range(0, 2**n, 2): for j in range(0, 2**n, 2):
for i in range(0, 2**n, 2): for i in range(0, 2**n, 2):
transposed_density_op[i:i+2, j:j+2] = density_op[i:i+2, j:j+2].transpose() transposed_density_op[i:i+2, j:j+2] = density_op[i:i+2, j:j+2].transpose()
return transposed_density_op return transposed_density_op
def negativity(density_op): def negativity(density_op):
r"""计算输入量子态的 Negativity :math:`N = ||\frac{\rho^{T_A}-1}{2}||`。 r"""计算输入量子态的 Negativity :math:`N = ||\frac{\rho^{T_A}-1}{2}||`。
...@@ -406,12 +404,13 @@ def negativity(density_op): ...@@ -406,12 +404,13 @@ def negativity(density_op):
# Calculate through the equivalent expression N = sum(abs(\lambda_i)) when \lambda_i<0 # Calculate through the equivalent expression N = sum(abs(\lambda_i)) when \lambda_i<0
n = 0 n = 0
eigen_val, _ = numpy.linalg.eig(density_op_T) eigen_val, _ = np.linalg.eig(density_op_T)
for val in eigen_val: for val in eigen_val:
if val < 0: if val < 0:
n = n + numpy.abs(val) n = n + np.abs(val)
return n return n
def logarithmic_negativity(density_op): def logarithmic_negativity(density_op):
r"""计算输入量子态的 Logarithmic Negativity :math:`E_N = ||\rho^{T_A}||`。 r"""计算输入量子态的 Logarithmic Negativity :math:`E_N = ||\rho^{T_A}||`。
...@@ -438,7 +437,7 @@ def logarithmic_negativity(density_op): ...@@ -438,7 +437,7 @@ def logarithmic_negativity(density_op):
n = negativity(density_op) n = negativity(density_op)
# Calculate through the equivalent expression # Calculate through the equivalent expression
log2_n = numpy.log2(2*n + 1) log2_n = np.log2(2*n + 1)
return log2_n return log2_n
......
paddlepaddle==1.8.5 paddlepaddle>=2.0.1
networkx>=2.4 scipy
matplotlib>=3.3.0 networkx
interval>=1.0.0 matplotlib
progressbar>=2.5 interval
\ No newline at end of file tqdm
\ No newline at end of file
...@@ -23,7 +23,7 @@ with open("README.md", "r", encoding="utf-8") as fh: ...@@ -23,7 +23,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
setuptools.setup( setuptools.setup(
name='paddle-quantum', name='paddle-quantum',
version='1.2.0', version='2.0.0',
author='Institute for Quantum Computing, Baidu INC.', author='Institute for Quantum Computing, Baidu INC.',
author_email='quantum@baidu.com', author_email='quantum@baidu.com',
description='Paddle Quantum is a quantum machine learning (QML) toolkit developed based on Baidu PaddlePaddle.', description='Paddle Quantum is a quantum machine learning (QML) toolkit developed based on Baidu PaddlePaddle.',
...@@ -32,7 +32,7 @@ setuptools.setup( ...@@ -32,7 +32,7 @@ setuptools.setup(
url='http://qml.baidu.com', url='http://qml.baidu.com',
packages=['paddle_quantum', 'paddle_quantum.GIBBS', 'paddle_quantum.QAOA', 'paddle_quantum.SSVQE', 'paddle_quantum.VQE', 'paddle_quantum.VQSD', packages=['paddle_quantum', 'paddle_quantum.GIBBS', 'paddle_quantum.QAOA', 'paddle_quantum.SSVQE', 'paddle_quantum.VQE', 'paddle_quantum.VQSD',
'paddle_quantum.GIBBS.example', 'paddle_quantum.QAOA.example', 'paddle_quantum.SSVQE.example', 'paddle_quantum.VQE.example', 'paddle_quantum.VQSD.example'], 'paddle_quantum.GIBBS.example', 'paddle_quantum.QAOA.example', 'paddle_quantum.SSVQE.example', 'paddle_quantum.VQE.example', 'paddle_quantum.VQSD.example'],
install_requires=['paddlepaddle==1.8.5', 'networkx>=2.4', 'matplotlib>=3.3.0', 'interval>=1.0.0', 'progressbar>=2.5'], install_requires=['paddlepaddle>=2.0.1', 'scipy', 'networkx', 'matplotlib', 'interval', 'tqdm'],
python_requires='>=3.6, <4', python_requires='>=3.6, <4',
classifiers=[ classifiers=[
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -84,8 +84,8 @@ ...@@ -84,8 +84,8 @@
"from numpy import array, concatenate, zeros\n", "from numpy import array, concatenate, zeros\n",
"from numpy import pi as PI\n", "from numpy import pi as PI\n",
"from numpy import trace as np_trace\n", "from numpy import trace as np_trace\n",
"from paddle import fluid\n", "import paddle\n",
"from paddle.complex import matmul, trace\n", "from paddle import matmul, trace, real\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.state import density_op\n", "from paddle_quantum.state import density_op\n",
"from paddle_quantum.utils import state_fidelity, partial_trace, pauli_str_to_matrix" "from paddle_quantum.utils import state_fidelity, partial_trace, pauli_str_to_matrix"
...@@ -129,7 +129,7 @@ ...@@ -129,7 +129,7 @@
"source": [ "source": [
"N = 4 # 量子神经网络的宽度\n", "N = 4 # 量子神经网络的宽度\n",
"N_SYS_B = 3 # 用于生成吉布斯态的子系统B的量子比特数 \n", "N_SYS_B = 3 # 用于生成吉布斯态的子系统B的量子比特数 \n",
"SEED = 14 # 固定随机种子\n", "SEED = 16 # 固定随机种子\n",
"beta = 1.5 # 设置逆温度参数 beta" "beta = 1.5 # 设置逆温度参数 beta"
] ]
}, },
...@@ -249,17 +249,17 @@ ...@@ -249,17 +249,17 @@
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Net(fluid.dygraph.Layer):\n", "class Net(paddle.nn.Layer):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " def __init__(self, shape, dtype='float64'):\n",
" low=0.0, high=2*PI, seed=SEED), dtype='float64'):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
" \n", " \n",
" # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n", " # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n",
" self.theta = self.create_parameter(shape=shape, \n", " self.theta = self.create_parameter(shape=shape,\n",
" attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # 初始化 rho = |0..0><0..0| 的密度矩阵\n", " # 初始化 rho = |0..0><0..0| 的密度矩阵\n",
" self.initial_state=fluid.dygraph.to_variable(density_op(N))\n", " self.initial_state = paddle.to_tensor(density_op(N))\n",
"\n", "\n",
" # 定义损失函数和前向传播机制\n", " # 定义损失函数和前向传播机制\n",
" def forward(self, H, N, N_SYS_B, D):\n", " def forward(self, H, N, N_SYS_B, D):\n",
...@@ -272,9 +272,9 @@ ...@@ -272,9 +272,9 @@
" \n", " \n",
" # 计算三个子损失函数\n", " # 计算三个子损失函数\n",
" rho_B_squre = matmul(rho_B, rho_B)\n", " rho_B_squre = matmul(rho_B, rho_B)\n",
" loss1 = (trace(matmul(rho_B, H))).real\n", " loss1 = real(trace(matmul(rho_B, H)))\n",
" loss2 = (trace(rho_B_squre)).real * 2 / beta\n", " loss2 = real(trace(rho_B_squre)) * 2 / beta\n",
" loss3 = - ((trace(matmul(rho_B_squre, rho_B))).real + 3) / (2 * beta)\n", " loss3 = -(real(trace(matmul(rho_B_squre, rho_B))) + 3) / (2 * beta)\n",
" \n", " \n",
" # 最终的损失函数\n", " # 最终的损失函数\n",
" loss = loss1 + loss2 + loss3 \n", " loss = loss1 + loss2 + loss3 \n",
...@@ -323,7 +323,7 @@ ...@@ -323,7 +323,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"- 当训练模型的各项参数都设置完成后,我们将数据转化为 Paddle 动态图中的变量,进而进行量子神经网络的训练。\n", "- 当训练模型的各项参数都设置完成后,我们将数据转化为 Paddle 中的张量,进而进行量子神经网络的训练。\n",
"- 训练过程中我们用的是 [Adam Optimizer](https://www.paddlepaddle.org.cn/documentation/docs/zh/api_cn/optimizer_cn/AdagradOptimizer_cn.html),也可以调用 Paddle 中提供的其他优化器。\n", "- 训练过程中我们用的是 [Adam Optimizer](https://www.paddlepaddle.org.cn/documentation/docs/zh/api_cn/optimizer_cn/AdagradOptimizer_cn.html),也可以调用 Paddle 中提供的其他优化器。\n",
"- 我们将训练过程中的结果依次输出。\n", "- 我们将训练过程中的结果依次输出。\n",
"- 特别地,我们依次输出了我们学习到的量子态 $\\rho_B(\\theta)$ 与吉布斯态 $\\rho_G$ 的保真度,保真度越高说明QNN输出的态越接近于吉布斯态。" "- 特别地,我们依次输出了我们学习到的量子态 $\\rho_B(\\theta)$ 与吉布斯态 $\\rho_G$ 的保真度,保真度越高说明QNN输出的态越接近于吉布斯态。"
...@@ -343,48 +343,45 @@ ...@@ -343,48 +343,45 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 10 loss: -3.1189 fid: 0.9504\n", "iter: 10 loss: -3.1085 fid: 0.9241\n",
"iter: 20 loss: -3.3502 fid: 0.9846\n", "iter: 20 loss: -3.3375 fid: 0.9799\n",
"iter: 30 loss: -3.3630 fid: 0.9873\n", "iter: 30 loss: -3.3692 fid: 0.9897\n",
"iter: 40 loss: -3.4087 fid: 0.9948\n", "iter: 40 loss: -3.3990 fid: 0.9929\n",
"iter: 50 loss: -3.4110 fid: 0.9953\n" "iter: 50 loss: -3.4133 fid: 0.9959\n"
] ]
} }
], ],
"source": [ "source": [
"# 初始化paddle动态图机制\n", "paddle.seed(SEED)\n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable\n", "# 我们需要将 Numpy array 转换成 Paddle 中支持的 Tensor\n",
" H = fluid.dygraph.to_variable(hamiltonian)\n", "H = paddle.to_tensor(hamiltonian)\n",
"\n", "\n",
" # 确定网络的参数维度\n", "# 确定网络的参数维度\n",
" net = Net(shape=[D + 1, N, 1])\n", "net = Net(shape=[D + 1, N, 1])\n",
"\n", "\n",
" # 一般来说,我们利用Adam优化器来获得相对好的收敛,\n", "# 一般来说,我们利用 Adam 优化器来获得相对好的收敛,\n",
" # 当然你可以改成SGD或者是RMS prop.\n", "# 当然你可以改成 SGD 或者是 RMS prop.\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, \n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" parameter_list=net.parameters())\n",
"\n", "\n",
" # 优化循环\n", "# 优化循环\n",
" for itr in range(1, ITR + 1):\n", "for itr in range(1, ITR + 1):\n",
" \n", " \n",
" # 前向传播计算损失函数并返回生成的量子态 rho_B\n", " # 前向传播计算损失函数并返回生成的量子态 rho_B\n",
" loss, rho_B = net(H, N, N_SYS_B, D)\n", " loss, rho_B = net(H, N, N_SYS_B, D)\n",
" \n", " \n",
" # 在动态图机制下,反向传播极小化损失函数\n", " # 反向传播极小化损失函数\n",
" loss.backward()\n", " loss.backward()\n",
" opt.minimize(loss)\n", " opt.minimize(loss)\n",
" net.clear_gradients()\n", " opt.clear_grad()\n",
"\n", "\n",
" # 转换成 Numpy array 用以计算量子态的保真度 F(rho_B, rho_G)\n", " # 转换成 Numpy array 用以计算量子态的保真度 F(rho_B, rho_G)\n",
" rho_B = rho_B.numpy()\n", " rho_B = rho_B.numpy()\n",
" fid = state_fidelity(rho_B, rho_G)\n", " fid = state_fidelity(rho_B, rho_G)\n",
" \n", " \n",
" # 打印训练结果\n", " # 打印训练结果\n",
" if itr % 10 == 0:\n", " if itr % 10 == 0:\n",
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), \n", " print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:', '%.4f' % fid)"
" 'fid:', '%.4f' % fid)"
] ]
}, },
{ {
...@@ -405,6 +402,8 @@ ...@@ -405,6 +402,8 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"_______\n",
"\n",
"## 参考文献" "## 参考文献"
] ]
}, },
...@@ -438,7 +437,7 @@ ...@@ -438,7 +437,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.10" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -81,8 +81,8 @@ ...@@ -81,8 +81,8 @@
"from numpy import array, concatenate, zeros\n", "from numpy import array, concatenate, zeros\n",
"from numpy import pi as PI\n", "from numpy import pi as PI\n",
"from numpy import trace as np_trace\n", "from numpy import trace as np_trace\n",
"from paddle import fluid\n", "import paddle\n",
"from paddle.complex import matmul, trace\n", "from paddle import matmul, trace, real\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.state import density_op\n", "from paddle_quantum.state import density_op\n",
"from paddle_quantum.utils import state_fidelity, partial_trace, pauli_str_to_matrix" "from paddle_quantum.utils import state_fidelity, partial_trace, pauli_str_to_matrix"
...@@ -126,7 +126,7 @@ ...@@ -126,7 +126,7 @@
"source": [ "source": [
"N = 4 # The width of the QNN\n", "N = 4 # The width of the QNN\n",
"N_SYS_B = 3 # The number of qubits of subsystem B used to generate the Gibbs state\n", "N_SYS_B = 3 # The number of qubits of subsystem B used to generate the Gibbs state\n",
"SEED = 14 # Fixed random seed\n", "SEED = 16 # Fixed random seed\n",
"beta = 1.5 # Set the inverse temperature parameter beta" "beta = 1.5 # Set the inverse temperature parameter beta"
] ]
}, },
...@@ -245,17 +245,17 @@ ...@@ -245,17 +245,17 @@
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Net(fluid.dygraph.Layer):\n", "class Net(paddle.nn.Layer):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " def __init__(self, shape, dtype='float64'):\n",
" low=0.0, high=2*PI, seed=SEED), dtype='float64'):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
" \n", " \n",
" # Initialize parameters theta with the uniform distribution of [0, 2*pi]\n", " # Initialize parameters theta with the uniform distribution of [0, 2*pi]\n",
" self.theta = self.create_parameter(shape=shape,\n", " self.theta = self.create_parameter(shape=shape,\n",
" attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # Initialize the density matrix rho = |0..0><0..0|\n", " # Initialize the density matrix rho = |0..0><0..0|\n",
" self.initial_state=fluid.dygraph.to_variable(density_op(N))\n", " self.initial_state = paddle.to_tensor(density_op(N))\n",
"\n", "\n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self, H, N, N_SYS_B, D):\n", " def forward(self, H, N, N_SYS_B, D):\n",
...@@ -268,9 +268,9 @@ ...@@ -268,9 +268,9 @@
" \n", " \n",
" # Calculate the three parts of the loss function\n", " # Calculate the three parts of the loss function\n",
" rho_B_squre = matmul(rho_B, rho_B)\n", " rho_B_squre = matmul(rho_B, rho_B)\n",
" loss1 = (trace(matmul(rho_B, H))).real\n", " loss1 = real(trace(matmul(rho_B, H)))\n",
" loss2 = (trace(rho_B_squre)).real * 2 / beta\n", " loss2 = real(trace(rho_B_squre)) * 2 / beta\n",
" loss3 =-((trace(matmul(rho_B_squre, rho_B))).real + 3) / (2 * beta)\n", " loss3 = -(real(trace(matmul(rho_B_squre, rho_B))) + 3) / (2 * beta)\n",
" \n", " \n",
" # Final loss function\n", " # Final loss function\n",
" loss = loss1 + loss2 + loss3\n", " loss = loss1 + loss2 + loss3\n",
...@@ -319,7 +319,7 @@ ...@@ -319,7 +319,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"- After all the training model parameters are set, we convert the data into variables in the PaddlePaddle dynamic graph and then train the QNN.\n", "- After all the training model parameters are set, we convert the data into Tensor in PaddlePaddle and then train the QNN.\n",
"- During training, we use [Adam Optimizer](https://www.paddlepaddle.org.cn/documentation/docs/en/api/optimizer/AdamOptimizer.html). Other optimizers are also provided in PaddlePaddle.\n", "- During training, we use [Adam Optimizer](https://www.paddlepaddle.org.cn/documentation/docs/en/api/optimizer/AdamOptimizer.html). Other optimizers are also provided in PaddlePaddle.\n",
"- We output the results of the training process in turn.\n", "- We output the results of the training process in turn.\n",
"- In particular, we sequentially output the fidelity of the quantum state $\\rho_B(\\theta)$ and Gibbs state $\\rho_G$ we learned. The higher the fidelity, the closer the QNN output state is to Gibbs state." "- In particular, we sequentially output the fidelity of the quantum state $\\rho_B(\\theta)$ and Gibbs state $\\rho_G$ we learned. The higher the fidelity, the closer the QNN output state is to Gibbs state."
...@@ -339,48 +339,45 @@ ...@@ -339,48 +339,45 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 10 loss: -3.1189 fid: 0.9504\n", "iter: 10 loss: -3.1085 fid: 0.9241\n",
"iter: 20 loss: -3.3502 fid: 0.9846\n", "iter: 20 loss: -3.3375 fid: 0.9799\n",
"iter: 30 loss: -3.3630 fid: 0.9873\n", "iter: 30 loss: -3.3692 fid: 0.9897\n",
"iter: 40 loss: -3.4087 fid: 0.9948\n", "iter: 40 loss: -3.3990 fid: 0.9929\n",
"iter: 50 loss: -3.4110 fid: 0.9953\n" "iter: 50 loss: -3.4133 fid: 0.9959\n"
] ]
} }
], ],
"source": [ "source": [
"# Initialize PaddlePaddle dynamic graph mechanism\n", "paddle.seed(SEED)\n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" # Convert Numpy array to variable supported in PaddlePaddle dynamic graph mode\n", "# Convert Numpy array to Tensor supported in PaddlePaddle\n",
" H = fluid.dygraph.to_variable(hamiltonian)\n", "H = paddle.to_tensor(hamiltonian)\n",
"\n", "\n",
" # Determine the parameter dimension of the network\n", "# Determine the parameter dimension of the network\n",
" net = Net(shape=[D + 1, N, 1])\n", "net = Net(shape=[D + 1, N, 1])\n",
"\n", "\n",
" # Generally speaking, we use Adam optimizer to get relatively good convergence\n", "# Generally speaking, we use Adam optimizer to get relatively good convergence\n",
" # Of course, it can be changed to SGD or RMS prop.\n", "# Of course, it can be changed to SGD or RMS prop.\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR,\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" parameter_list=net.parameters())\n",
"\n", "\n",
" # Optimization loops\n", "# Optimization loops\n",
" for itr in range(1, ITR + 1):\n", "for itr in range(1, ITR + 1):\n",
" \n", " \n",
" # Run forward propagation to calculate the loss function and return the generated quantum state rho_B\n", " # Run forward propagation to calculate the loss function and return the generated quantum state rho_B\n",
" loss, rho_B = net(H, N, N_SYS_B, D)\n", " loss, rho_B = net(H, N, N_SYS_B, D)\n",
" \n", " \n",
" # Under the dynamic graph mechanism, run back propagation to minimize the loss function\n", " # Run back propagation to minimize the loss function\n",
" loss.backward()\n", " loss.backward()\n",
" opt.minimize(loss)\n", " opt.minimize(loss)\n",
" net.clear_gradients()\n", " opt.clear_grad()\n",
"\n", "\n",
" # Convert to Numpy array to calculate the fidelity of the quantum state F(rho_B, rho_G)\n", " # Convert to Numpy array to calculate the fidelity of the quantum state F(rho_B, rho_G)\n",
" rho_B = rho_B.numpy()\n", " rho_B = rho_B.numpy()\n",
" fid = state_fidelity(rho_B, rho_G)\n", " fid = state_fidelity(rho_B, rho_G)\n",
" \n", " \n",
" # Print training results\n", " # Print training results\n",
" if itr% 10 == 0:\n", " if itr% 10 == 0:\n",
" print('iter:', itr,'loss:','%.4f'% loss.numpy(),\n", " print('iter:', itr,'loss:','%.4f'% loss.numpy(),'fid:','%.4f'% fid)"
" 'fid:','%.4f'% fid)"
] ]
}, },
{ {
...@@ -401,6 +398,8 @@ ...@@ -401,6 +398,8 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"_______\n",
"\n",
"## References" "## References"
] ]
}, },
...@@ -434,7 +433,7 @@ ...@@ -434,7 +433,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.10" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "personal-pride",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 纠缠蒸馏 -- BBPSSW 协议\n", "# 纠缠蒸馏 -- BBPSSW 协议\n",
...@@ -12,6 +13,7 @@ ...@@ -12,6 +13,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "consistent-hungary",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## 概述\n", "## 概述\n",
...@@ -21,6 +23,7 @@ ...@@ -21,6 +23,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "mighty-model",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### 贝尔态\n", "### 贝尔态\n",
...@@ -60,10 +63,11 @@ ...@@ -60,10 +63,11 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 1,
"id": "bearing-millennium",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:13:13.334418Z", "end_time": "2021-02-23T09:09:21.025275Z",
"start_time": "2021-01-27T06:13:12.936569Z" "start_time": "2021-02-23T09:09:20.598689Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -88,6 +92,7 @@ ...@@ -88,6 +92,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "stuck-ballot",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### 量化纠缠资源\n", "### 量化纠缠资源\n",
...@@ -135,7 +140,6 @@ ...@@ -135,7 +140,6 @@
"0 & 1 & 0 & 0\\\\\n", "0 & 1 & 0 & 0\\\\\n",
"0 & 0 & 0 & 1\n", "0 & 0 & 0 & 1\n",
"\\end{bmatrix}\n", "\\end{bmatrix}\n",
".\n",
"\\tag{6}\n", "\\tag{6}\n",
"\\end{align*}\n", "\\end{align*}\n",
"$$\n", "$$\n",
...@@ -146,10 +150,11 @@ ...@@ -146,10 +150,11 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 2,
"id": "unique-class",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:13:17.858393Z", "end_time": "2021-02-23T09:09:26.267474Z",
"start_time": "2021-01-27T06:13:13.360104Z" "start_time": "2021-02-23T09:09:23.986839Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -183,6 +188,7 @@ ...@@ -183,6 +188,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "needed-arkansas",
"metadata": {}, "metadata": {},
"source": [ "source": [
"在纠缠蒸馏方案中,我们通常使用蒸馏后的输出态 $\\rho_{out}$ 和贝尔态 $|\\Phi^+\\rangle$ 之间的**保真度 (state fidelity)** $ F $ 来量化蒸馏方案的性能,其中\n", "在纠缠蒸馏方案中,我们通常使用蒸馏后的输出态 $\\rho_{out}$ 和贝尔态 $|\\Phi^+\\rangle$ 之间的**保真度 (state fidelity)** $ F $ 来量化蒸馏方案的性能,其中\n",
...@@ -205,10 +211,11 @@ ...@@ -205,10 +211,11 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 3,
"id": "assigned-laptop",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:13:17.894726Z", "end_time": "2021-02-23T09:09:28.053216Z",
"start_time": "2021-01-27T06:13:17.865157Z" "start_time": "2021-02-23T09:09:28.045377Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -231,6 +238,7 @@ ...@@ -231,6 +238,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "indian-brooks",
"metadata": {}, "metadata": {},
"source": [ "source": [
"经过以上准备,我们可以开始介绍 BBPSSW 协议。\n", "经过以上准备,我们可以开始介绍 BBPSSW 协议。\n",
...@@ -279,6 +287,7 @@ ...@@ -279,6 +287,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "noted-elimination",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Paddle Quantum 代码实现\n", "## Paddle Quantum 代码实现\n",
...@@ -289,24 +298,26 @@ ...@@ -289,24 +298,26 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 4,
"id": "inside-vulnerability",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:13:18.591447Z", "end_time": "2021-02-23T09:09:36.454093Z",
"start_time": "2021-01-27T06:13:17.898635Z" "start_time": "2021-02-23T09:09:36.069131Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle.fluid as fluid\n",
"from paddle_quantum.locc import LoccNet\n", "from paddle_quantum.locc import LoccNet\n",
"from paddle.complex import matmul, trace\n", "from paddle import matmul, trace\n",
"import paddle\n",
"from paddle_quantum.state import bell_state, isotropic_state\n", "from paddle_quantum.state import bell_state, isotropic_state\n",
"from paddle_quantum.utils import logarithmic_negativity, is_ppt" "from paddle_quantum.utils import logarithmic_negativity, is_ppt"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "appropriate-smith",
"metadata": {}, "metadata": {},
"source": [ "source": [
"为了方便起见,我们在此处计算 BBPSSW 的度量,然后与模拟结果进行比较。" "为了方便起见,我们在此处计算 BBPSSW 的度量,然后与模拟结果进行比较。"
...@@ -315,10 +326,11 @@ ...@@ -315,10 +326,11 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 5,
"id": "considerable-premises",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:13:18.602671Z", "end_time": "2021-02-23T09:09:38.315327Z",
"start_time": "2021-01-27T06:13:18.593932Z" "start_time": "2021-02-23T09:09:38.302105Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -336,6 +348,7 @@ ...@@ -336,6 +348,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "sudden-interstate",
"metadata": {}, "metadata": {},
"source": [ "source": [
"在我们的示例中,输入态是 Isotropic 态,其中 $ p = 0.7 $,也就是说\n", "在我们的示例中,输入态是 Isotropic 态,其中 $ p = 0.7 $,也就是说\n",
...@@ -349,10 +362,11 @@ ...@@ -349,10 +362,11 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 6,
"id": "sized-rover",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:13:18.656842Z", "end_time": "2021-02-23T09:09:41.248379Z",
"start_time": "2021-01-27T06:13:18.627418Z" "start_time": "2021-02-23T09:09:41.226807Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -378,6 +392,7 @@ ...@@ -378,6 +392,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "increasing-national",
"metadata": {}, "metadata": {},
"source": [ "source": [
"然后,我们模拟 BBPSSW 协议,并检查结果是否与理论相符。" "然后,我们模拟 BBPSSW 协议,并检查结果是否与理论相符。"
...@@ -386,10 +401,11 @@ ...@@ -386,10 +401,11 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 7,
"id": "motivated-association",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:13:18.726120Z", "end_time": "2021-02-23T09:09:44.342242Z",
"start_time": "2021-01-27T06:13:18.691784Z" "start_time": "2021-02-23T09:09:44.322978Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -409,15 +425,15 @@ ...@@ -409,15 +425,15 @@
" self.add_new_party(2, party_name='Bob')\n", " self.add_new_party(2, party_name='Bob')\n",
" \n", " \n",
" # 定义输入量子态 rho_in\n", " # 定义输入量子态 rho_in\n",
" _state = fluid.dygraph.to_variable(isotropic_state(2, p))\n", " _state = paddle.to_tensor(isotropic_state(2, p))\n",
" \n", " \n",
" # ('Alice', 0) 代表 Alice 的第一个量子比特 A0\n", " # ('Alice', 0) 代表 Alice 的第一个量子比特 A0\n",
" # ('Bob', 0) 代表 Bob 的第一个量子比特 B0\n", " # ('Bob', 0) 代表 Bob 的第一个量子比特 B0\n",
" self.set_init_status(_state, [('Alice', 0), ('Bob', 0)]) \n", " self.set_init_state(_state, [('Alice', 0), ('Bob', 0)]) \n",
" \n", " \n",
" # ('Alice', 1) 代表 Alice 的第二个量子比特 A1\n", " # ('Alice', 1) 代表 Alice 的第二个量子比特 A1\n",
" # ('Bob', 1) 代表 Bob 的第二个量子比特 B1\n", " # ('Bob', 1) 代表 Bob 的第二个量子比特 B1\n",
" self.set_init_status(_state, [('Alice', 1), ('Bob', 1)]) \n", " self.set_init_state(_state, [('Alice', 1), ('Bob', 1)]) \n",
" \n", " \n",
" def BBPSSW(self):\n", " def BBPSSW(self):\n",
" status = self.init_status\n", " status = self.init_status\n",
...@@ -450,10 +466,11 @@ ...@@ -450,10 +466,11 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 8,
"id": "enormous-workplace",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:13:18.897415Z", "end_time": "2021-02-23T09:10:17.568446Z",
"start_time": "2021-01-27T06:13:18.768481Z" "start_time": "2021-02-23T09:10:17.205178Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -476,37 +493,36 @@ ...@@ -476,37 +493,36 @@
} }
], ],
"source": [ "source": [
"with fluid.dygraph.guard():\n", "# 运行 BBPSSW 协议\n",
" \n", "status_fin = LOCC().BBPSSW()\n",
" # 运行 BBPSSW 协议\n", "\n",
" status_fin = LOCC().BBPSSW()\n", "# 计算保真度\n",
" \n", "target_state = paddle.to_tensor(bell_state(2))\n",
" # 计算保真度\n", "fidelity = 0\n",
" target_state = fluid.dygraph.to_variable(bell_state(2))\n", "for status in status_fin:\n",
" fidelity = 0\n", " fidelity += paddle.real(trace(matmul(target_state, status.state)))\n",
" for status in status_fin:\n", "fidelity /= len(status_fin)\n",
" fidelity += trace(matmul(target_state, status.state)).real\n", "\n",
" fidelity /= len(status_fin)\n", "# 计算成功概率\n",
" \n", "suc_rate = sum([status.prob for status in status_fin])\n",
" # 计算成功概率\n", "fidelity_in,_,_ = BBPSSW_metrics(p)\n",
" suc_rate = sum([status.prob for status in status_fin])\n", "\n",
" fidelity_in,_,_ = BBPSSW_metrics(p)\n", "# 输出模拟结果\n",
" \n", "print(f\"输入态的保真度是: {fidelity_in:.5f}\")\n",
" # 输出模拟结果\n", "print(f\"蒸馏后的量子态保真度是: {fidelity.numpy()[0]:.5f}\")\n",
" print(f\"输入态的保真度是: {fidelity_in:.5f}\")\n", "print(f\"蒸馏成功的概率是: {suc_rate.numpy()[0]:#.3%}\")\n",
" print(f\"蒸馏后的量子态保真度是: {fidelity.numpy()[0]:.5f}\")\n", "\n",
" print(f\"蒸馏成功的概率是: {suc_rate.numpy()[0]:#.3%}\")\n", "# 打印输出态\n",
" \n", "rho_out = status_fin[0].state.numpy()\n",
" # 打印输出态\n", "print(\"========================================================\")\n",
" rho_out = status_fin[0].state.numpy()\n", "print(f\"输出态是:\\n {rho_out}\")\n",
" print(\"========================================================\")\n", "print(f\"初始 logarithmic negativity 是: {logarithmic_negativity(isotropic_state(2,p))}\")\n",
" print(f\"输出态是:\\n {rho_out}\")\n", "print(f\"蒸馏后 logarithmic negativity 是: {logarithmic_negativity(rho_out)}\")"
" print(f\"初始 logarithmic negativity 是: {logarithmic_negativity(isotropic_state(2,p))}\")\n",
" print(f\"蒸馏后 logarithmic negativity 是: {logarithmic_negativity(rho_out)}\")"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "progressive-church",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## 结论\n", "## 结论\n",
...@@ -526,6 +542,7 @@ ...@@ -526,6 +542,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "appropriate-postage",
"metadata": {}, "metadata": {},
"source": [ "source": [
"---\n", "---\n",
......
...@@ -61,8 +61,8 @@ ...@@ -61,8 +61,8 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T16:21:09.977831Z", "end_time": "2021-02-23T09:10:37.924098Z",
"start_time": "2021-01-26T16:21:09.281510Z" "start_time": "2021-02-23T09:10:37.671533Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -134,7 +134,6 @@ ...@@ -134,7 +134,6 @@
"0 & 1 & 0 & 0\\\\\n", "0 & 1 & 0 & 0\\\\\n",
"0 & 0 & 0 & 1\n", "0 & 0 & 0 & 1\n",
"\\end{bmatrix}\n", "\\end{bmatrix}\n",
".\n",
"\\tag{6}\n", "\\tag{6}\n",
"\\end{align*}\n", "\\end{align*}\n",
"$$\n", "$$\n",
...@@ -147,8 +146,8 @@ ...@@ -147,8 +146,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T16:21:16.275733Z", "end_time": "2021-02-23T09:10:43.024928Z",
"start_time": "2021-01-26T16:21:10.519841Z" "start_time": "2021-02-23T09:10:41.024088Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -206,8 +205,8 @@ ...@@ -206,8 +205,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T16:21:19.607822Z", "end_time": "2021-02-23T09:10:45.384306Z",
"start_time": "2021-01-26T16:21:19.578880Z" "start_time": "2021-02-23T09:10:45.376793Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -295,16 +294,16 @@ ...@@ -295,16 +294,16 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T16:21:22.649950Z", "end_time": "2021-02-23T09:10:48.714566Z",
"start_time": "2021-01-26T16:21:22.011428Z" "start_time": "2021-02-23T09:10:48.322765Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle.fluid as fluid\n",
"from paddle_quantum.locc import LoccNet\n", "from paddle_quantum.locc import LoccNet\n",
"from paddle.complex import matmul, trace\n", "from paddle import matmul, trace\n",
"import paddle\n",
"from paddle_quantum.state import bell_state, isotropic_state\n", "from paddle_quantum.state import bell_state, isotropic_state\n",
"from paddle_quantum.utils import logarithmic_negativity, is_ppt" "from paddle_quantum.utils import logarithmic_negativity, is_ppt"
] ]
...@@ -321,8 +320,8 @@ ...@@ -321,8 +320,8 @@
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T16:21:23.353264Z", "end_time": "2021-02-23T09:10:50.880991Z",
"start_time": "2021-01-26T16:21:23.344765Z" "start_time": "2021-02-23T09:10:50.861653Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -355,8 +354,8 @@ ...@@ -355,8 +354,8 @@
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T16:21:24.513396Z", "end_time": "2021-02-23T09:10:52.180240Z",
"start_time": "2021-01-26T16:21:24.504698Z" "start_time": "2021-02-23T09:10:52.174381Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -392,30 +391,12 @@ ...@@ -392,30 +391,12 @@
"execution_count": 7, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T16:21:26.904523Z", "end_time": "2021-02-23T09:10:53.985975Z",
"start_time": "2021-01-26T16:21:26.696414Z" "start_time": "2021-02-23T09:10:53.973998Z"
}, },
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [],
{
"name": "stdout",
"output_type": "stream",
"text": [
"The fidelity of the input quantum state is: 0.77500\n",
"The fidelity of the purified quantum state is: 0.81376\n",
"The probability of successful purification is: 74.500%\n",
"========================================================\n",
"The output state is:\n",
" [[0.48489933+0.j 0. +0.j 0. +0.j 0.32885906+0.j]\n",
" [0. +0.j 0.01510067+0.j 0. +0.j 0. +0.j]\n",
" [0. +0.j 0. +0.j 0.01510067+0.j 0. +0.j]\n",
" [0.32885906+0.j 0. +0.j 0. +0.j 0.48489933+0.j]]\n",
"The initial logarithmic negativity is: 0.6322682154995127\n",
"The final logarithmic negativity is: 0.7026724166123284\n"
]
}
],
"source": [ "source": [
"class LOCC(LoccNet):\n", "class LOCC(LoccNet):\n",
" def __init__(self):\n", " def __init__(self):\n",
...@@ -432,15 +413,15 @@ ...@@ -432,15 +413,15 @@
" self.add_new_party(2, party_name='Bob')\n", " self.add_new_party(2, party_name='Bob')\n",
" \n", " \n",
" # Define the input quantum states rho_in\n", " # Define the input quantum states rho_in\n",
" _state = fluid.dygraph.to_variable(isotropic_state(2, p))\n", " _state = paddle.to_tensor(isotropic_state(2, p))\n",
" \n", " \n",
" # ('Alice', 0) means Alice's first qubit A0\n", " # ('Alice', 0) means Alice's first qubit A0\n",
" # ('Bob', 0) means Bob's first qubit B0\n", " # ('Bob', 0) means Bob's first qubit B0\n",
" self.set_init_status(_state, [('Alice', 0), ('Bob', 0)]) \n", " self.set_init_state(_state, [('Alice', 0), ('Bob', 0)]) \n",
" \n", " \n",
" # ('Alice', 1) means Alice's second qubit A1\n", " # ('Alice', 1) means Alice's second qubit A1\n",
" # ('Bob', 1) means Bob's second qubit B1\n", " # ('Bob', 1) means Bob's second qubit B1\n",
" self.set_init_status(_state, [('Alice', 1), ('Bob', 1)]) \n", " self.set_init_state(_state, [('Alice', 1), ('Bob', 1)]) \n",
" \n", " \n",
" def BBPSSW(self):\n", " def BBPSSW(self):\n",
" status = self.init_status\n", " status = self.init_status\n",
...@@ -467,37 +448,63 @@ ...@@ -467,37 +448,63 @@
" # Leaving only Alice’s first qubit and Bob’s first qubit A0&B0 as the memory register\n", " # Leaving only Alice’s first qubit and Bob’s first qubit A0&B0 as the memory register\n",
" status_fin = self.partial_state(status_mid, [('Alice', 0), ('Bob', 0)])\n", " status_fin = self.partial_state(status_mid, [('Alice', 0), ('Bob', 0)])\n",
" \n", " \n",
" return status_fin\n", " return status_fin"
" \n", ]
"\n", },
"# Turn on dynamic computational graph\n", {
"with fluid.dygraph.guard():\n", "cell_type": "code",
" \n", "execution_count": 8,
" # Run BBPSSW protocol\n", "metadata": {
" status_fin = LOCC().BBPSSW()\n", "ExecuteTime": {
" \n", "end_time": "2021-02-23T09:10:58.444882Z",
" # Calculate fidelity\n", "start_time": "2021-02-23T09:10:58.274024Z"
" target_state = fluid.dygraph.to_variable(bell_state(2))\n", }
" fidelity = 0\n", },
" for status in status_fin:\n", "outputs": [
" fidelity += trace(matmul(target_state, status.state)).real\n", {
" fidelity /= len(status_fin)\n", "name": "stdout",
" \n", "output_type": "stream",
" # Calculate success rate\n", "text": [
" suc_rate = sum([status.prob for status in status_fin])\n", "The fidelity of the input quantum state is: 0.77500\n",
" fidelity_in,_,_ = BBPSSW_metrics(p)\n", "The fidelity of the purified quantum state is: 0.81376\n",
" \n", "The probability of successful purification is: 74.500%\n",
" # Output simulation results\n", "========================================================\n",
" print(f\"The fidelity of the input quantum state is: {fidelity_in:.5f}\")\n", "The output state is:\n",
" print(f\"The fidelity of the purified quantum state is: {fidelity.numpy()[0]:.5f}\")\n", " [[0.48489933+0.j 0. +0.j 0. +0.j 0.32885906+0.j]\n",
" print(f\"The probability of successful purification is: {suc_rate.numpy()[0]:#.3%}\")\n", " [0. +0.j 0.01510067+0.j 0. +0.j 0. +0.j]\n",
" \n", " [0. +0.j 0. +0.j 0.01510067+0.j 0. +0.j]\n",
" # Print the output state\n", " [0.32885906+0.j 0. +0.j 0. +0.j 0.48489933+0.j]]\n",
" rho_out = status_fin[0].state.numpy()\n", "The initial logarithmic negativity is: 0.6322682154995127\n",
" print(\"========================================================\")\n", "The final logarithmic negativity is: 0.7026724166123284\n"
" print(f\"The output state is:\\n {rho_out}\")\n", ]
" print(f\"The initial logarithmic negativity is: {logarithmic_negativity(isotropic_state(2,p))}\")\n", }
" print(f\"The final logarithmic negativity is: {logarithmic_negativity(rho_out)}\")" ],
"source": [
"# Run BBPSSW protocol\n",
"status_fin = LOCC().BBPSSW()\n",
"\n",
"# Calculate fidelity\n",
"target_state = paddle.to_tensor(bell_state(2))\n",
"fidelity = 0\n",
"for status in status_fin:\n",
" fidelity += paddle.real(trace(matmul(target_state, status.state)))\n",
"fidelity /= len(status_fin)\n",
"\n",
"# Calculate success rate\n",
"suc_rate = sum([status.prob for status in status_fin])\n",
"fidelity_in,_,_ = BBPSSW_metrics(p)\n",
"\n",
"# Output simulation results\n",
"print(f\"The fidelity of the input quantum state is: {fidelity_in:.5f}\")\n",
"print(f\"The fidelity of the purified quantum state is: {fidelity.numpy()[0]:.5f}\")\n",
"print(f\"The probability of successful purification is: {suc_rate.numpy()[0]:#.3%}\")\n",
"\n",
"# Print the output state\n",
"rho_out = status_fin[0].state.numpy()\n",
"print(\"========================================================\")\n",
"print(f\"The output state is:\\n {rho_out}\")\n",
"print(f\"The initial logarithmic negativity is: {logarithmic_negativity(isotropic_state(2,p))}\")\n",
"print(f\"The final logarithmic negativity is: {logarithmic_negativity(rho_out)}\")"
] ]
}, },
{ {
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
"\n", "\n",
"$$\n", "$$\n",
"\\rho_{\\text{diag}} = p_1 | \\Phi^+\\rangle \\langle \\Phi^+ | + p_2 | \\Psi^+\\rangle \\langle \\Psi^+ | + \n", "\\rho_{\\text{diag}} = p_1 | \\Phi^+\\rangle \\langle \\Phi^+ | + p_2 | \\Psi^+\\rangle \\langle \\Psi^+ | + \n",
"p_3 | \\Phi^-\\rangle \\langle \\Phi^- | + p_4 | \\Psi^-\\rangle \\langle \\Psi^- |.\n", "p_3 | \\Phi^-\\rangle \\langle \\Phi^- | + p_4 | \\Psi^-\\rangle \\langle \\Psi^- |,\n",
"\\tag{2}\n", "\\tag{2}\n",
"$$\n", "$$\n",
"\n", "\n",
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
"在蒸馏成功的情况下,$A_0$ 和 $B_0$ 作为输出比特,他们的输出态 $\\rho_{out}$ 的和目标态之间的保真度将会提升。输出态的保真度 $F_{out}$ 为\n", "在蒸馏成功的情况下,$A_0$ 和 $B_0$ 作为输出比特,他们的输出态 $\\rho_{out}$ 的和目标态之间的保真度将会提升。输出态的保真度 $F_{out}$ 为\n",
"\n", "\n",
"$$\n", "$$\n",
"F_{out} = \\frac{p_1^2 + p_4^2}{(p_1 + p_4)^2 + (p_2 + p_3)^2},\n", "F_{out} = \\frac{p_1^2 + p_4^2}{(p_1 + p_4)^2 + (p_2 + p_3)^2}.\n",
"\\tag{3}\n", "\\tag{3}\n",
"$$\n", "$$\n",
"\n", "\n",
...@@ -90,16 +90,16 @@ ...@@ -90,16 +90,16 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:10:17.461722Z", "end_time": "2021-02-23T09:13:09.766714Z",
"start_time": "2021-01-27T06:10:09.975500Z" "start_time": "2021-02-23T09:13:07.457788Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle.fluid as fluid\n",
"from paddle_quantum.locc import LoccNet\n", "from paddle_quantum.locc import LoccNet\n",
"from paddle.complex import matmul, trace\n", "from paddle import matmul, trace\n",
"import paddle\n",
"from paddle_quantum.state import bell_state, isotropic_state, bell_diagonal_state\n", "from paddle_quantum.state import bell_state, isotropic_state, bell_diagonal_state\n",
"from paddle_quantum.utils import negativity, logarithmic_negativity, is_ppt" "from paddle_quantum.utils import negativity, logarithmic_negativity, is_ppt"
] ]
...@@ -124,8 +124,8 @@ ...@@ -124,8 +124,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:10:17.561117Z", "end_time": "2021-02-23T09:13:09.792624Z",
"start_time": "2021-01-27T06:10:17.465773Z" "start_time": "2021-02-23T09:13:09.769360Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -172,29 +172,11 @@ ...@@ -172,29 +172,11 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T06:10:17.887395Z", "end_time": "2021-02-23T09:13:11.302009Z",
"start_time": "2021-01-27T06:10:17.588579Z" "start_time": "2021-02-23T09:13:11.286937Z"
} }
}, },
"outputs": [ "outputs": [],
{
"name": "stdout",
"output_type": "stream",
"text": [
"输入态的保真度为: 0.70000\n",
"蒸馏后的保真度为: 0.78800\n",
"蒸馏的成功率为: 62.500%\n",
"========================================================\n",
"蒸馏后的态是:\n",
" [[ 0.45 +0.j 0. -0.j -0. +0.j 0.338-0.j]\n",
" [ 0. +0.j 0.05 +0.j 0.002-0.j 0. -0.j]\n",
" [ 0. +0.j 0.002+0.j 0.05 -0.j 0. -0.j]\n",
" [ 0.338+0.j -0. -0.j 0. +0.j 0.45 +0.j]]\n",
"初始态的 negativity: 0.19999999999999993\n",
"输出态的 negativity: 0.28800000000000003\n"
]
}
],
"source": [ "source": [
"class LOCC(LoccNet):\n", "class LOCC(LoccNet):\n",
" def __init__(self):\n", " def __init__(self):\n",
...@@ -209,19 +191,19 @@ ...@@ -209,19 +191,19 @@
" self.add_new_party(2, party_name='Bob')\n", " self.add_new_party(2, party_name='Bob')\n",
" \n", " \n",
" # 定义一个贝尔对角态,四个系数对应 p1, p2, p3, p4\n", " # 定义一个贝尔对角态,四个系数对应 p1, p2, p3, p4\n",
" _state = fluid.dygraph.to_variable(bell_diagonal_state(p, (1-p)/2, (1-p)/3, (1-p)/6))\n", " _state = paddle.to_tensor(bell_diagonal_state(p, (1-p)/2, (1-p)/3, (1-p)/6))\n",
" \n", " \n",
" # ('Alice', 0) 表示 Alice 的第一个量子比特 A0\n", " # ('Alice', 0) 表示 Alice 的第一个量子比特 A0\n",
" # ('Bob', 0) 表示 Bob 的第一个量子比特 B0\n", " # ('Bob', 0) 表示 Bob 的第一个量子比特 B0\n",
" self.set_init_status(_state, [('Alice', 0), ('Bob', 0)]) \n", " self.set_init_state(_state, [('Alice', 0), ('Bob', 0)]) \n",
" \n", " \n",
" # ('Alice', 1) 表示 Alice 的第二个量子比特 A1\n", " # ('Alice', 1) 表示 Alice 的第二个量子比特 A1\n",
" # ('Bob', 1) 表示 Bob 的第二个量子比特 B1\n", " # ('Bob', 1) 表示 Bob 的第二个量子比特 B1\n",
" self.set_init_status(_state, [('Alice', 1), ('Bob', 1)]) \n", " self.set_init_state(_state, [('Alice', 1), ('Bob', 1)]) \n",
" \n", " \n",
" # 创建两个参数 theta1 和 theta2 用来分别存储 Alice 和 Bob 的本地旋转门的角度\n", " # 创建两个参数 theta1 和 theta2 用来分别存储 Alice 和 Bob 的本地旋转门的角度\n",
" self.theta1 = fluid.dygraph.to_variable(np.array([np.pi/2, np.pi/2], dtype='float64'))\n", " self.theta1 = paddle.to_tensor(np.array([np.pi/2, np.pi/2], dtype='float64'))\n",
" self.theta2 = fluid.dygraph.to_variable(np.array([-np.pi/2, -np.pi/2], dtype='float64'))\n", " self.theta2 = paddle.to_tensor(np.array([-np.pi/2, -np.pi/2], dtype='float64'))\n",
" \n", " \n",
" def DEJMPS(self):\n", " def DEJMPS(self):\n",
" status = self.init_status\n", " status = self.init_status\n",
...@@ -252,38 +234,64 @@ ...@@ -252,38 +234,64 @@
" # status_fin 即为 A0 和 B0 的二比特态\n", " # status_fin 即为 A0 和 B0 的二比特态\n",
" status_fin = self.partial_state(status_mid, [('Alice', 0), ('Bob', 0)])\n", " status_fin = self.partial_state(status_mid, [('Alice', 0), ('Bob', 0)])\n",
" \n", " \n",
" return status_fin\n", " return status_fin"
" \n", ]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-23T09:13:16.728882Z",
"start_time": "2021-02-23T09:13:16.547804Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"输入态的保真度为: 0.70000\n",
"蒸馏后的保真度为: 0.78800\n",
"蒸馏的成功率为: 62.500%\n",
"========================================================\n",
"蒸馏后的态是:\n",
" [[ 0.45 +0.j 0. -0.j -0. +0.j 0.338-0.j]\n",
" [ 0. +0.j 0.05 +0.j 0.002-0.j 0. -0.j]\n",
" [ 0. +0.j 0.002+0.j 0.05 -0.j 0. -0.j]\n",
" [ 0.338+0.j -0. -0.j 0. +0.j 0.45 +0.j]]\n",
"初始态的 negativity: 0.19999999999999993\n",
"输出态的 negativity: 0.28800000000000003\n"
]
}
],
"source": [
"# 运行 DEJMPS 协议\n",
"status_fin = LOCC().DEJMPS()\n",
"\n", "\n",
"# 开启动态计算图\n", "# 生成我们想要的目标态\n",
"with fluid.dygraph.guard():\n", "target_state = paddle.to_tensor(bell_state(2))\n",
" \n", "\n",
" # 运行 DEJMPS 协议\n", "# 计算他们之间的保真度\n",
" status_fin = LOCC().DEJMPS()\n", "fidelity = 0\n",
" \n", "for status in status_fin:\n",
" # 生成我们想要的目标态\n", " fidelity += paddle.real(trace(matmul(target_state, status.state)))\n",
" target_state = fluid.dygraph.to_variable(bell_state(2))\n", "fidelity /= len(status_fin)\n",
" \n", "\n",
" # 计算他们之间的保真度\n", "# 计算成功率\n",
" fidelity = 0\n", "suc_rate = sum([status.prob for status in status_fin])\n",
" for status in status_fin:\n", "\n",
" fidelity += trace(matmul(target_state, status.state)).real\n", "# 输出结果\n",
" fidelity /= len(status_fin)\n", "print(f\"输入态的保真度为: {p:.5f}\")\n",
" \n", "print(f\"蒸馏后的保真度为: {fidelity.numpy()[0]:.5f}\")\n",
" # 计算成功率\n", "print(f\"蒸馏的成功率为: {suc_rate.numpy()[0]:#.3%}\")\n",
" suc_rate = sum([status.prob for status in status_fin])\n", "\n",
" \n", "# 输出终态\n",
" # 输出结果\n", "rho_out = status_fin[0].state.numpy()\n",
" print(f\"输入态的保真度为: {p:.5f}\")\n", "print(\"========================================================\")\n",
" print(f\"蒸馏后的保真度为: {fidelity.numpy()[0]:.5f}\")\n", "print(f\"蒸馏后的态是:\\n {np.around(rho_out, 4)}\")\n",
" print(f\"蒸馏的成功率为: {suc_rate.numpy()[0]:#.3%}\")\n", "print(f\"初始态的 negativity: {negativity(bell_diagonal_state(p, (1-p)/2, (1-p)/3, (1-p)/6))}\")\n",
" \n", "print(f\"输出态的 negativity: {negativity(rho_out)}\")"
" # 输出终态\n",
" rho_out = status_fin[0].state.numpy()\n",
" print(\"========================================================\")\n",
" print(f\"蒸馏后的态是:\\n {np.around(rho_out, 4)}\")\n",
" print(f\"初始态的 negativity: {negativity(bell_diagonal_state(p, (1-p)/2, (1-p)/3, (1-p)/6))}\")\n",
" print(f\"输出态的 negativity: {negativity(rho_out)}\")"
] ]
}, },
{ {
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
"\n", "\n",
"$$\n", "$$\n",
"\\rho_{\\text{diag}} = p_1 | \\Phi^+\\rangle \\langle \\Phi^+ | + p_2 | \\Psi^+\\rangle \\langle \\Psi^+ | + \n", "\\rho_{\\text{diag}} = p_1 | \\Phi^+\\rangle \\langle \\Phi^+ | + p_2 | \\Psi^+\\rangle \\langle \\Psi^+ | + \n",
"p_3 | \\Phi^-\\rangle \\langle \\Phi^- | + p_4 | \\Psi^-\\rangle \\langle \\Psi^- |.\n", "p_3 | \\Phi^-\\rangle \\langle \\Phi^- | + p_4 | \\Psi^-\\rangle \\langle \\Psi^- |,\n",
"\\tag{2}\n", "\\tag{2}\n",
"$$\n", "$$\n",
"\n", "\n",
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
"After the distillation, the final state $\\rho_{out}$ of entangled pair $A_0, B_0$ will have higher fidelity than the initial state $\\rho$. The fidelity of the final state $F_{out}$ is\n", "After the distillation, the final state $\\rho_{out}$ of entangled pair $A_0, B_0$ will have higher fidelity than the initial state $\\rho$. The fidelity of the final state $F_{out}$ is\n",
"\n", "\n",
"$$\n", "$$\n",
"F_{out} = \\frac{p_1^2 + p_4^2}{(p_1 + p_4)^2 + (p_2 + p_3)^2},\n", "F_{out} = \\frac{p_1^2 + p_4^2}{(p_1 + p_4)^2 + (p_2 + p_3)^2}.\n",
"\\tag{3}\n", "\\tag{3}\n",
"$$\n", "$$\n",
"\n", "\n",
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Simulation with Paddle Quantum\n", "## Simulation with Paddle Quantum\n",
"First, we need to import relevant packages" "First, we need to import relevant packages:"
] ]
}, },
{ {
...@@ -86,16 +86,16 @@ ...@@ -86,16 +86,16 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T16:59:07.977165Z", "end_time": "2021-02-23T09:13:33.570407Z",
"start_time": "2021-01-25T16:59:06.564863Z" "start_time": "2021-02-23T09:13:30.832819Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle.fluid as fluid\n",
"from paddle_quantum.locc import LoccNet\n", "from paddle_quantum.locc import LoccNet\n",
"from paddle.complex import matmul, trace\n", "from paddle import matmul, trace\n",
"import paddle\n",
"from paddle_quantum.state import bell_state, isotropic_state, bell_diagonal_state\n", "from paddle_quantum.state import bell_state, isotropic_state, bell_diagonal_state\n",
"from paddle_quantum.utils import negativity, logarithmic_negativity, is_ppt" "from paddle_quantum.utils import negativity, logarithmic_negativity, is_ppt"
] ]
...@@ -104,7 +104,7 @@ ...@@ -104,7 +104,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"First, let us see the theoretical result of applying the **DEJMPS protocol** to the state\n", "Let us see the theoretical result of applying the **DEJMPS protocol** to the state\n",
"\n", "\n",
"$$\n", "$$\n",
"\\rho = p_1 | \\Phi^+\\rangle \\langle \\Phi^+ | + \\frac{1-p_1}{2} | \\Psi^+\\rangle \\langle \\Psi^+ |+ \n", "\\rho = p_1 | \\Phi^+\\rangle \\langle \\Phi^+ | + \\frac{1-p_1}{2} | \\Psi^+\\rangle \\langle \\Psi^+ |+ \n",
...@@ -120,8 +120,8 @@ ...@@ -120,8 +120,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T16:59:11.804714Z", "end_time": "2021-02-23T09:13:33.689788Z",
"start_time": "2021-01-25T16:59:11.771952Z" "start_time": "2021-02-23T09:13:33.669677Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -165,32 +165,14 @@ ...@@ -165,32 +165,14 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T16:59:15.223963Z", "end_time": "2021-02-23T09:13:35.397596Z",
"start_time": "2021-01-25T16:59:14.574124Z" "start_time": "2021-02-23T09:13:35.383842Z"
} }
}, },
"outputs": [ "outputs": [],
{
"name": "stdout",
"output_type": "stream",
"text": [
"The fidelity of the input quantum state is: 0.70000\n",
"The fidelity of the purified quantum state is: 0.78800\n",
"The probability of successful purification is: 62.500%\n",
"========================================================\n",
"The output state is:\n",
" [[0.45 -0.j 0. +0.j 0. -0.j 0.338-0.j]\n",
" [0. -0.j 0.05 +0.j 0.002-0.j 0. +0.j]\n",
" [0. -0.j 0.002+0.j 0.05 -0.j 0. -0.j]\n",
" [0.338+0.j 0. +0.j 0. +0.j 0.45 -0.j]]\n",
"The initial negativity is: 0.19999999999999993\n",
"The final negativity is: 0.2880000000000001\n"
]
}
],
"source": [ "source": [
"class LOCC(LoccNet):\n", "class LOCC(LoccNet):\n",
" def __init__(self):\n", " def __init__(self):\n",
...@@ -207,19 +189,19 @@ ...@@ -207,19 +189,19 @@
" self.add_new_party(2, party_name='Bob')\n", " self.add_new_party(2, party_name='Bob')\n",
" \n", " \n",
" # Define the input quantum states rho_in\n", " # Define the input quantum states rho_in\n",
" _state = fluid.dygraph.to_variable(bell_diagonal_state(p, (1-p)/2, (1-p)/3, (1-p)/6))\n", " _state = paddle.to_tensor(bell_diagonal_state(p, (1-p)/2, (1-p)/3, (1-p)/6))\n",
" \n", " \n",
" # ('Alice', 0) means Alice's first qubit A0\n", " # ('Alice', 0) means Alice's first qubit A0\n",
" # ('Bob', 0) means Bob's first qubit B0\n", " # ('Bob', 0) means Bob's first qubit B0\n",
" self.set_init_status(_state, [('Alice', 0), ('Bob', 0)]) \n", " self.set_init_state(_state, [('Alice', 0), ('Bob', 0)]) \n",
" \n", " \n",
" # ('Alice', 1) means Alice's second qubit A1\n", " # ('Alice', 1) means Alice's second qubit A1\n",
" # ('Bob', 1) means Bob's second qubit B1\n", " # ('Bob', 1) means Bob's second qubit B1\n",
" self.set_init_status(_state, [('Alice', 1), ('Bob', 1)]) \n", " self.set_init_state(_state, [('Alice', 1), ('Bob', 1)]) \n",
" \n", " \n",
" # Set the angles of the Rx gates\n", " # Set the angles of the Rx gates\n",
" self.theta1 = fluid.dygraph.to_variable(np.array([np.pi/2, np.pi/2], dtype='float64'))\n", " self.theta1 = paddle.to_tensor(np.array([np.pi/2, np.pi/2], dtype='float64'))\n",
" self.theta2 = fluid.dygraph.to_variable(np.array([-np.pi/2, -np.pi/2], dtype='float64'))\n", " self.theta2 = paddle.to_tensor(np.array([-np.pi/2, -np.pi/2], dtype='float64'))\n",
" \n", " \n",
" def DEJMPS(self):\n", " def DEJMPS(self):\n",
" status = self.init_status\n", " status = self.init_status\n",
...@@ -250,36 +232,62 @@ ...@@ -250,36 +232,62 @@
" # Leaving only Alice’s first qubit and Bob’s first qubit A0&B0 as the memory register\n", " # Leaving only Alice’s first qubit and Bob’s first qubit A0&B0 as the memory register\n",
" status_fin = self.partial_state(status_mid, [('Alice', 0), ('Bob', 0)])\n", " status_fin = self.partial_state(status_mid, [('Alice', 0), ('Bob', 0)])\n",
" \n", " \n",
" return status_fin\n", " return status_fin"
" \n", ]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-23T09:13:43.070659Z",
"start_time": "2021-02-23T09:13:42.826239Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The fidelity of the input quantum state is: 0.70000\n",
"The fidelity of the purified quantum state is: 0.78800\n",
"The probability of successful purification is: 62.500%\n",
"========================================================\n",
"The output state is:\n",
" [[ 0.45 +0.j 0. -0.j -0. +0.j 0.338-0.j]\n",
" [ 0. +0.j 0.05 +0.j 0.002-0.j 0. -0.j]\n",
" [ 0. +0.j 0.002+0.j 0.05 -0.j 0. -0.j]\n",
" [ 0.338+0.j -0. -0.j 0. +0.j 0.45 +0.j]]\n",
"The initial negativity is: 0.19999999999999993\n",
"The final negativity is: 0.28800000000000003\n"
]
}
],
"source": [
"# Run DEJMPS protocol\n",
"status_fin = LOCC().DEJMPS()\n",
"\n", "\n",
"# Turn on dynamic computational graph\n", "# Calculate fidelity\n",
"with fluid.dygraph.guard():\n", "target_state = paddle.to_tensor(bell_state(2))\n",
" \n", "fidelity = 0\n",
" # Run DEJMPS protocol\n", "for status in status_fin:\n",
" status_fin = LOCC().DEJMPS()\n", " fidelity += paddle.real(trace(matmul(target_state, status.state)))\n",
" \n", "fidelity /= len(status_fin)\n",
" # Calculate fidelity\n", "\n",
" target_state = fluid.dygraph.to_variable(bell_state(2))\n", "# Calculate success rate\n",
" fidelity = 0\n", "suc_rate = sum([status.prob for status in status_fin])\n",
" for status in status_fin:\n", "\n",
" fidelity += trace(matmul(target_state, status.state)).real\n", "# Output simulation results\n",
" fidelity /= len(status_fin)\n", "print(f\"The fidelity of the input quantum state is: {p:.5f}\")\n",
" \n", "print(f\"The fidelity of the purified quantum state is: {fidelity.numpy()[0]:.5f}\")\n",
" # Calculate success rate\n", "print(f\"The probability of successful purification is: {suc_rate.numpy()[0]:#.3%}\")\n",
" suc_rate = sum([status.prob for status in status_fin])\n", "\n",
" \n", "# Print the output state\n",
" # Output simulation results\n", "rho_out = status_fin[0].state.numpy()\n",
" print(f\"The fidelity of the input quantum state is: {p:.5f}\")\n", "print(\"========================================================\")\n",
" print(f\"The fidelity of the purified quantum state is: {fidelity.numpy()[0]:.5f}\")\n", "print(f\"The output state is:\\n {np.around(rho_out,4)}\")\n",
" print(f\"The probability of successful purification is: {suc_rate.numpy()[0]:#.3%}\")\n", "print(f\"The initial negativity is: {negativity(bell_diagonal_state(p, (1-p)/2, (1-p)/3, (1-p)/6))}\")\n",
" \n", "print(f\"The final negativity is: {negativity(rho_out)}\")"
" # Print the output state\n",
" rho_out = status_fin[0].state.numpy()\n",
" print(\"========================================================\")\n",
" print(f\"The output state is:\\n {np.around(rho_out,4)}\")\n",
" print(f\"The initial negativity is: {negativity(bell_diagonal_state(p, (1-p)/2, (1-p)/3, (1-p)/6))}\")\n",
" print(f\"The final negativity is: {negativity(rho_out)}\")"
] ]
}, },
{ {
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
"为了通过 LOCC 完成纠缠蒸馏,我们需要两位身处于两个地方的参与者 $A$ (Alice) 和 $B$ (Bob)。在最开始的时候,他们共享四份纠缠量子比特对 $\\rho_{A_0B_0}, \\rho_{A_1B_1}, \\rho_{A_2B_2}$ 和 $\\rho_{A_3B_3}$,每一份的初始态都为 $\\rho_{in} = \\rho_{\\text{iso}}(p =0.7)$。如此,Alice 手中有四个量子比特,分别是 $A_0, A_1, A_2, A_3$;对应地,Bob 手中也有四个量子比特,$B_0, B_1, B_2, B_3$。完成上述初始化后,Alice 和 Bob 需要选择通讯的轮数(communication round)$r$,即他们需要交换经典信息(可以是各自的测量结果)多少次。为了方便讨论,这里我们选择通讯轮数为 1。接下来, Alice 和 Bob 需要进行下述操作使得 LOCCNet 学习出最优的本地操作(Local Operation)。更准确的说法是学习出代表本地操作的量子神经网络(Quantum Neural Network, QNN)的最优参数。\n", "为了通过 LOCC 完成纠缠蒸馏,我们需要两位身处于两个地方的参与者 $A$ (Alice) 和 $B$ (Bob)。在最开始的时候,他们共享四份纠缠量子比特对 $\\rho_{A_0B_0}, \\rho_{A_1B_1}, \\rho_{A_2B_2}$ 和 $\\rho_{A_3B_3}$,每一份的初始态都为 $\\rho_{in} = \\rho_{\\text{iso}}(p =0.7)$。如此,Alice 手中有四个量子比特,分别是 $A_0, A_1, A_2, A_3$;对应地,Bob 手中也有四个量子比特,$B_0, B_1, B_2, B_3$。完成上述初始化后,Alice 和 Bob 需要选择通讯的轮数(communication round)$r$,即他们需要交换经典信息(可以是各自的测量结果)多少次。为了方便讨论,这里我们选择通讯轮数为 1。接下来, Alice 和 Bob 需要进行下述操作使得 LOCCNet 学习出最优的本地操作(Local Operation)。更准确的说法是学习出代表本地操作的量子神经网络(Quantum Neural Network, QNN)的最优参数。\n",
"\n", "\n",
"1. 设计一个 QNN 架构 $U(\\boldsymbol\\theta)$ 如图 1所示,其中 $R(\\theta)$ 表示单比特通用门。我们可以通过调用 Paddle Quantum 中的 `u3(theta, phi, lam, which_qubit)` 来实现该旋转门。\n", "1. 设计一个 QNN 架构 $U(\\boldsymbol\\theta)$ 如图 1所示,其中 $R(\\theta)$ 表示单比特通用门。我们可以通过调用 Paddle Quantum 中的 `u3(theta, phi, lam, which_qubit)` 来实现该旋转门。\n",
"2. 在量子比特通过步骤 1. 中设计的 QNN 电路后,Alice 和 Bob 需要对除去 $A_0$ and $B_0$ 的剩余量子比特进行测量。测量结果 $M = \\{m_{A_1}m_{B_1}, m_{A_2}m_{B_2}, m_{A_3}m_{B_3}\\}$ 需要通过经典方式告知对方。\n", "2. 在量子比特通过步骤 1. 中设计的 QNN 电路后,Alice 和 Bob 需要对除去 $A_0$ $B_0$ 的剩余量子比特进行测量。测量结果 $M = \\{m_{A_1}m_{B_1}, m_{A_2}m_{B_2}, m_{A_3}m_{B_3}\\}$ 需要通过经典方式告知对方。\n",
"3. 如果每对的测量结果都相同,即 $m_{A_1}m_{B_1}, m_{A_2}m_{B_2}, m_{A_3}m_{B_3}$ 的结果要么为 00, 要么为 11。这种情况下,我们称蒸馏成功,然后剩余的一对量子比特 $A_0B_0$ 作为输出态被保存,标记为 $\\rho_{AB}'$。如果测量结果不满足上述判定结果,则蒸馏失败,需要丢弃量子比特 $A_0B_0$。\n", "3. 如果每对的测量结果都相同,即 $m_{A_1}m_{B_1}, m_{A_2}m_{B_2}, m_{A_3}m_{B_3}$ 的结果要么为 00, 要么为 11。这种情况下,我们称蒸馏成功,然后剩余的一对量子比特 $A_0B_0$ 作为输出态被保存,标记为 $\\rho_{AB}'$。如果测量结果不满足上述判定结果,则蒸馏失败,需要丢弃量子比特 $A_0B_0$。\n",
"4. 这里,我们在所以蒸馏成功的情况下定义一个累积的损失函数 $L = \\sum_{m_{A_j}m_{B_j}\\in \\{00,11\\}} \\big(1- \\text{Tr}(\\rho_{tar}\\rho_{AB}')\\big)$,其中 $\\text{Tr}(\\rho_{tar}\\rho_{AB}')$ 表示当前态 $\\rho_{AB}'$ 和目标态 $\\rho_{tar}=\\lvert\\Phi^+\\rangle \\langle \\Phi^+\\rvert$ 之间的态重叠。\n", "4. 这里,我们在所以蒸馏成功的情况下定义一个累积的损失函数 $L = \\sum_{m_{A_j}m_{B_j}\\in \\{00,11\\}} \\big(1- \\text{Tr}(\\rho_{tar}\\rho_{AB}')\\big)$,其中 $\\text{Tr}(\\rho_{tar}\\rho_{AB}')$ 表示当前态 $\\rho_{AB}'$ 和目标态 $\\rho_{tar}=\\lvert\\Phi^+\\rangle \\langle \\Phi^+\\rvert$ 之间的态重叠。\n",
"5. 使用梯度下降的优化方案来更新 QNN 中的参数使得损失函数最小化。\n", "5. 使用梯度下降的优化方案来更新 QNN 中的参数使得损失函数最小化。\n",
...@@ -87,15 +87,15 @@ ...@@ -87,15 +87,15 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T07:03:59.029140Z", "end_time": "2021-03-09T06:14:25.259102Z",
"start_time": "2021-01-27T07:03:52.520296Z" "start_time": "2021-03-09T06:14:21.079745Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle.fluid as fluid\n", "from paddle import matmul, trace\n",
"from paddle.complex import matmul, trace\n", "import paddle\n",
"from paddle_quantum.locc import LoccAnsatz, LoccNet, LoccParty, LoccStatus\n", "from paddle_quantum.locc import LoccAnsatz, LoccNet, LoccParty, LoccStatus\n",
"from paddle_quantum.state import isotropic_state, bell_state\n", "from paddle_quantum.state import isotropic_state, bell_state\n",
"from paddle_quantum.utils import logarithmic_negativity" "from paddle_quantum.utils import logarithmic_negativity"
...@@ -113,8 +113,8 @@ ...@@ -113,8 +113,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T07:03:59.082475Z", "end_time": "2021-03-09T06:14:25.296793Z",
"start_time": "2021-01-27T07:03:59.036365Z" "start_time": "2021-03-09T06:14:25.270201Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -132,21 +132,22 @@ ...@@ -132,21 +132,22 @@
" self.add_new_party(4, party_name=\"Bob\")\n", " self.add_new_party(4, party_name=\"Bob\")\n",
" \n", " \n",
" # Alice 的参数\n", " # Alice 的参数\n",
" self.theta_1 = self.create_parameter(shape=[8, 3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n", " self.theta_1 = self.create_parameter(shape=[8, 3], default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n",
" \n", " \n",
" # Bob 的参数\n", " # Bob 的参数\n",
" self.theta_2 = self.create_parameter(shape=[8, 3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n", " self.theta_2 = self.create_parameter(shape=[8, 3], default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n",
" \n", " \n",
" # 生成输入态 isotropic state\n", " # 生成输入态 isotropic state\n",
" _state = fluid.dygraph.to_variable(isotropic_state(2, 0.7))\n", " _state = paddle.to_tensor(isotropic_state(2, 0.7))\n",
" \n",
" \n", " \n",
" # 初始化量子态\n", " # 初始化量子态\n",
" # ('Alice', 0) 代表 Alice 的第一个量子比特 A0\n", " # ('Alice', 0) 代表 Alice 的第一个量子比特 A0\n",
" # ('Bob', 0) 代表 Bob 的第一个量子比特 B0\n", " # ('Bob', 0) 代表 Bob 的第一个量子比特 B0\n",
" self.set_init_status(_state, [[\"Alice\", 0], [\"Bob\", 0]])\n", " self.set_init_state(_state, [[\"Alice\", 0], [\"Bob\", 0]])\n",
" self.set_init_status(_state, [[\"Alice\", 1], [\"Bob\", 1]])\n", " self.set_init_state(_state, [[\"Alice\", 1], [\"Bob\", 1]])\n",
" self.set_init_status(_state, [[\"Alice\", 2], [\"Bob\", 2]])\n", " self.set_init_state(_state, [[\"Alice\", 2], [\"Bob\", 2]])\n",
" self.set_init_status(_state, [[\"Alice\", 3], [\"Bob\", 3]])\n", " self.set_init_state(_state, [[\"Alice\", 3], [\"Bob\", 3]])\n",
"\n", "\n",
" def QNN(self, cir, theta):\n", " def QNN(self, cir, theta):\n",
" '''\n", " '''\n",
...@@ -188,12 +189,12 @@ ...@@ -188,12 +189,12 @@
" \n", " \n",
" # 取偏迹除去测量后的量子比特,只留下 A0&B0 \n", " # 取偏迹除去测量后的量子比特,只留下 A0&B0 \n",
" status_fin = self.partial_state(status1, [[\"Alice\", 0], [\"Bob\", 0]])\n", " status_fin = self.partial_state(status1, [[\"Alice\", 0], [\"Bob\", 0]])\n",
" target_state = fluid.dygraph.to_variable(bell_state(2))\n", " target_state = paddle.to_tensor(bell_state(2))\n",
" \n", " \n",
" # 计算损失函数\n", " # 计算损失函数\n",
" loss = 0\n", " loss = 0\n",
" for idx in range(0, len(status_fin)):\n", " for idx in range(0, len(status_fin)):\n",
" loss += 1 - trace(matmul(target_state, status_fin[idx].state)).real[0]\n", " loss += 1 - paddle.real(trace(matmul(target_state, status_fin[idx].state)))[0]\n",
" return loss, status_fin\n" " return loss, status_fin\n"
] ]
}, },
...@@ -209,8 +210,8 @@ ...@@ -209,8 +210,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T07:12:19.023140Z", "end_time": "2021-03-09T06:18:31.750336Z",
"start_time": "2021-01-27T07:03:59.103836Z" "start_time": "2021-03-09T06:14:25.304303Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -218,75 +219,73 @@ ...@@ -218,75 +219,73 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"itr 0: 5.974937567506047\n", "itr 0: 5.7033257831039315\n",
"itr 10: 1.3569325419999818\n", "itr 10: 1.552207114278755\n",
"itr 20: 1.1205194635673945\n", "itr 20: 0.8980303153930879\n",
"itr 30: 0.951684388970055\n", "itr 30: 0.7061224566044214\n",
"itr 40: 0.5876979234625004\n", "itr 40: 0.5713956826398692\n",
"itr 50: 0.5372695244330837\n", "itr 50: 0.5278055638406681\n",
"itr 60: 0.5199700730199454\n", "itr 60: 0.5121543497136843\n",
"itr 70: 0.5110181973259903\n", "itr 70: 0.5075981613869213\n",
"itr 80: 0.5064717635676458\n", "itr 80: 0.5052044047709767\n",
"itr 90: 0.5051218758007482\n", "itr 90: 0.5049323155027947\n",
"输入态的保真度为:0.77500\n", "输入态的保真度为:0.77500\n",
"输出态的保真度为:0.93688\n", "输出态的保真度为:0.93690\n",
"提纯成功率为:0.38654\n", "提纯成功率为:0.38654\n",
"========================================================\n", "========================================================\n",
"输出态为:\n", "输出态为:\n",
" [[ 4.790e-01+0.j 3.000e-04+0.0003j -3.000e-04+0.0003j\n", " [[ 4.790e-01+0.j -1.000e-04-0.j 1.000e-04-0.j\n",
" 4.579e-01+0.0004j]\n", " 4.579e-01+0.0005j]\n",
" [ 3.000e-04-0.0003j 2.100e-02-0.j -0.000e+00+0.j\n", " [-1.000e-04+0.j 2.100e-02+0.j 0.000e+00+0.j\n",
" 3.000e-04-0.0003j]\n", " -1.000e-04+0.j ]\n",
" [-3.000e-04-0.0003j -0.000e+00-0.j 2.100e-02+0.j\n", " [ 1.000e-04+0.j 0.000e+00-0.j 2.100e-02+0.j\n",
" -3.000e-04-0.0003j]\n", " 1.000e-04+0.0001j]\n",
" [ 4.579e-01-0.0004j 3.000e-04+0.0003j -3.000e-04+0.0003j\n", " [ 4.579e-01-0.0005j -1.000e-04-0.j 1.000e-04-0.0001j\n",
" 4.790e-01+0.j ]]\n", " 4.790e-01+0.j ]]\n",
"初始态的 logarithmic negativity 为: 0.6322682154995127\n", "初始态的 logarithmic negativity 为: 0.6322682154995127\n",
"输出态的 logarithmic negativity 为: 0.9059439306384385\n" "输出态的 logarithmic negativity 为: 0.9059639124992761\n"
] ]
} }
], ],
"source": [ "source": [
"ITR = 100 # 循环次数\n", "ITR = 100 # 循环次数\n",
"LR = 0.2 # 学习率\n", "LR = 0.2 # 学习率\n",
"paddle.seed(999)\n",
"\n", "\n",
"# 开启动态图模式\n", "net = LOCC()\n",
"with fluid.dygraph.guard(fluid.CPUPlace()):\n", "# 选择 Adam 优化器\n",
" net = LOCC()\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"loss_list = [] \n",
"\n", "\n",
" # 选择 Adam 优化器\n", "# 优化循环\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "for itr in range(ITR):\n",
" loss_list = [] \n", " loss, status_fin = net.New_Protocol()\n",
" \n", " # 反向传播\n",
" # 优化循环\n", " loss.backward() \n",
" for itr in range(ITR):\n", " opt.minimize(loss)\n",
" loss, status_fin = net.New_Protocol()\n", " # 清除梯度\n",
" # 反向传播\n", " opt.clear_grad() \n",
" loss.backward() \n", " loss_list.append(loss.numpy()[0])\n",
" opt.minimize(loss)\n", "\n",
" # 清除梯度\n", " # 打印训练结果\n",
" net.clear_gradients() \n", " if itr % 10 == 0:\n",
" loss_list.append(loss.numpy()[0])\n", " print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n",
" \n",
" # 打印训练结果\n",
" if itr % 10 == 0:\n",
" print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n",
"\n", "\n",
" # 计算输入态的保真度\n", "# 计算输入态的保真度\n",
" fidelity_in = (3 * 0.7 + 1) / 4\n", "fidelity_in = (3 * 0.7 + 1) / 4\n",
" # 计算输出态的保真度\n", "# 计算输出态的保真度\n",
" fidelity = (len(status_fin) - loss) / len(status_fin)\n", "fidelity = (len(status_fin) - loss) / len(status_fin)\n",
" # 计算成功率\n", "# 计算成功率\n",
" suc_rate = sum([s.prob for s in status_fin])\n", "suc_rate = sum([s.prob for s in status_fin])\n",
"\n", "\n",
" print(\"输入态的保真度为:%.5f\" % fidelity_in)\n", "print(\"输入态的保真度为:%.5f\" % fidelity_in)\n",
" print(\"输出态的保真度为:%.5f\" % fidelity.numpy()[0])\n", "print(\"输出态的保真度为:%.5f\" % fidelity.numpy()[0])\n",
" print(\"提纯成功率为:%.5f\" % suc_rate.numpy()[0])\n", "print(\"提纯成功率为:%.5f\" % suc_rate.numpy()[0])\n",
" rho_out = status_fin[0].state.numpy()\n", "rho_out = status_fin[0].state.numpy()\n",
" print(\"========================================================\")\n", "print(\"========================================================\")\n",
" print(f\"输出态为:\\n {np.around(rho_out, 4)}\")\n", "print(f\"输出态为:\\n {np.around(rho_out, 4)}\")\n",
" print(f\"初始态的 logarithmic negativity 为: {logarithmic_negativity(isotropic_state(2, 0.7))}\")\n", "print(f\"初始态的 logarithmic negativity 为: {logarithmic_negativity(isotropic_state(2, 0.7))}\")\n",
" print(f\"输出态的 logarithmic negativity 为: {logarithmic_negativity(rho_out)}\")" "print(f\"输出态的 logarithmic negativity 为: {logarithmic_negativity(rho_out)}\")"
] ]
}, },
{ {
...@@ -332,7 +331,7 @@ ...@@ -332,7 +331,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -90,15 +90,15 @@ ...@@ -90,15 +90,15 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T04:17:11.026674Z", "end_time": "2021-03-09T06:19:13.646334Z",
"start_time": "2021-01-27T04:17:04.505712Z" "start_time": "2021-03-09T06:19:10.780432Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle.fluid as fluid\n", "from paddle import matmul, trace\n",
"from paddle.complex import matmul, trace\n", "import paddle\n",
"from paddle_quantum.locc import LoccAnsatz, LoccNet, LoccParty, LoccStatus\n", "from paddle_quantum.locc import LoccAnsatz, LoccNet, LoccParty, LoccStatus\n",
"from paddle_quantum.state import isotropic_state, bell_state\n", "from paddle_quantum.state import isotropic_state, bell_state\n",
"from paddle_quantum.utils import logarithmic_negativity" "from paddle_quantum.utils import logarithmic_negativity"
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Secondly, we define the QNN and loss function" "Secondly, we define the QNN and loss function:"
] ]
}, },
{ {
...@@ -116,8 +116,8 @@ ...@@ -116,8 +116,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T04:17:11.074048Z", "end_time": "2021-03-09T06:19:13.700268Z",
"start_time": "2021-01-27T04:17:11.030252Z" "start_time": "2021-03-09T06:19:13.650127Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -137,19 +137,18 @@ ...@@ -137,19 +137,18 @@
" self.add_new_party(4, party_name=\"Bob\")\n", " self.add_new_party(4, party_name=\"Bob\")\n",
" \n", " \n",
" # Alice‘s params\n", " # Alice‘s params\n",
" self.theta_1 = self.create_parameter(shape=[8, 3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n", " self.theta_1 = self.create_parameter(shape=[8, 3], default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n",
" \n",
" # Bob's params\n", " # Bob's params\n",
" self.theta_2 = self.create_parameter(shape=[8, 3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n", " self.theta_2 = self.create_parameter(shape=[8, 3], default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n",
" \n", " \n",
" # Generate input isotropic states\n", " # Generate input isotropic states\n",
" _state = fluid.dygraph.to_variable(isotropic_state(2, 0.7))\n", " _state = paddle.to_tensor(isotropic_state(2, 0.7))\n",
" \n", " \n",
" # Distribute the pre-shared entangled states\n", " # Distribute the pre-shared entangled states\n",
" self.set_init_status(_state, [[\"Alice\", 0], [\"Bob\", 0]])\n", " self.set_init_state(_state, [[\"Alice\", 0], [\"Bob\", 0]])\n",
" self.set_init_status(_state, [[\"Alice\", 1], [\"Bob\", 1]])\n", " self.set_init_state(_state, [[\"Alice\", 1], [\"Bob\", 1]])\n",
" self.set_init_status(_state, [[\"Alice\", 2], [\"Bob\", 2]])\n", " self.set_init_state(_state, [[\"Alice\", 2], [\"Bob\", 2]])\n",
" self.set_init_status(_state, [[\"Alice\", 3], [\"Bob\", 3]])\n", " self.set_init_state(_state, [[\"Alice\", 3], [\"Bob\", 3]])\n",
"\n", "\n",
" def QNN(self, cir, theta):\n", " def QNN(self, cir, theta):\n",
" '''\n", " '''\n",
...@@ -191,12 +190,12 @@ ...@@ -191,12 +190,12 @@
" \n", " \n",
" # Trace out all the qubits but A_0 and B_0\n", " # Trace out all the qubits but A_0 and B_0\n",
" status_fin = self.partial_state(status1, [[\"Alice\", 0], [\"Bob\", 0]])\n", " status_fin = self.partial_state(status1, [[\"Alice\", 0], [\"Bob\", 0]])\n",
" target_state = fluid.dygraph.to_variable(bell_state(2))\n", " target_state = paddle.to_tensor(bell_state(2))\n",
" \n", " \n",
" # Calculate loss function\n", " # Calculate loss function\n",
" loss = 0\n", " loss = 0\n",
" for idx in range(0, len(status_fin)):\n", " for idx in range(0, len(status_fin)):\n",
" loss += 1 - trace(matmul(target_state, status_fin[idx].state)).real[0]\n", " loss += 1 - paddle.real(trace(matmul(target_state, status_fin[idx].state)))[0]\n",
" return loss, status_fin\n" " return loss, status_fin\n"
] ]
}, },
...@@ -212,8 +211,8 @@ ...@@ -212,8 +211,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T04:27:35.758702Z", "end_time": "2021-03-09T06:22:27.071785Z",
"start_time": "2021-01-27T04:17:11.098191Z" "start_time": "2021-03-09T06:19:13.706482Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -221,75 +220,73 @@ ...@@ -221,75 +220,73 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"itr 0: 6.313622673221091\n", "itr 0: 5.7033257831039315\n",
"itr 10: 1.5322711051309412\n", "itr 10: 1.552207114278755\n",
"itr 20: 0.7766710710147502\n", "itr 20: 0.8980303153930879\n",
"itr 30: 0.7114199957285438\n", "itr 30: 0.7061224566044214\n",
"itr 40: 0.6394957129763132\n", "itr 40: 0.5713956826398692\n",
"itr 50: 0.6085969124908581\n", "itr 50: 0.5278055638406681\n",
"itr 60: 0.5896473681859186\n", "itr 60: 0.5121543497136843\n",
"itr 70: 0.5234827632327423\n", "itr 70: 0.5075981613869213\n",
"itr 80: 0.5150627180761873\n", "itr 80: 0.5052044047709767\n",
"itr 90: 0.505887118309619\n", "itr 90: 0.5049323155027947\n",
"The fidelity of the input quantum state is:0.77500\n", "The fidelity of the input quantum state is:0.77500\n",
"The fidelity of the purified quantum state is: 0.93669\n", "The fidelity of the purified quantum state is: 0.93690\n",
"The probability of successful purification is:0.38664\n", "The probability of successful purification is:0.38654\n",
"========================================================\n", "========================================================\n",
"The output state is:\n", "The output state is:\n",
" [[ 4.787e-01+0.j -3.000e-04-0.0003j 3.000e-04-0.0003j\n", " [[ 4.790e-01+0.j -1.000e-04-0.j 1.000e-04-0.j\n",
" 4.580e-01+0.0004j]\n", " 4.579e-01+0.0005j]\n",
" [-3.000e-04+0.0003j 2.130e-02-0.j 0.000e+00+0.j\n", " [-1.000e-04+0.j 2.100e-02+0.j 0.000e+00+0.j\n",
" -3.000e-04+0.0003j]\n", " -1.000e-04+0.j ]\n",
" [ 3.000e-04+0.0003j 0.000e+00-0.j 2.130e-02+0.j\n", " [ 1.000e-04+0.j 0.000e+00-0.j 2.100e-02+0.j\n",
" 3.000e-04+0.0003j]\n", " 1.000e-04+0.0001j]\n",
" [ 4.580e-01-0.0004j -3.000e-04-0.0003j 3.000e-04-0.0003j\n", " [ 4.579e-01-0.0005j -1.000e-04-0.j 1.000e-04-0.0001j\n",
" 4.787e-01-0.j ]]\n", " 4.790e-01+0.j ]]\n",
"The initial logarithmic negativity is: 0.6322682154995127\n", "The initial logarithmic negativity is: 0.6322682154995127\n",
"The final logarithmic negativity is: 0.905643209528966\n" "The final logarithmic negativity is: 0.9059639124992761\n"
] ]
} }
], ],
"source": [ "source": [
"ITR = 100 # Number of iterations\n", "ITR = 100 # Number of iterations\n",
"LR = 0.2 # Learning rate\n", "LR = 0.2 # Learning rate\n",
"\n", "paddle.seed(999)\n",
"# Initialize the dynamic graph mode\n", "\n",
"with fluid.dygraph.guard(fluid.CPUPlace()):\n", "net = LOCC()\n",
" net = LOCC()\n", "\n",
"\n", "# Choose Adam optimizer\n",
" # Choose Adam optimizer\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "loss_list = [] \n",
" loss_list = [] \n", "\n",
" \n", "# Optimization loop\n",
" # Optimization loop\n", "for itr in range(ITR):\n",
" for itr in range(ITR):\n", " loss, status_fin = net.New_Protocol()\n",
" loss, status_fin = net.New_Protocol()\n", " # Backpropagation\n",
" # Backpropagation\n", " loss.backward() \n",
" loss.backward() \n", " opt.minimize(loss)\n",
" opt.minimize(loss)\n", " # Clean gradients\n",
" # Clean gradients\n", " opt.clear_grad() \n",
" net.clear_gradients() \n", " loss_list.append(loss.numpy()[0])\n",
" loss_list.append(loss.numpy()[0])\n", "\n",
" \n", " # Print training result\n",
" # Print training result\n", " if itr % 10 == 0:\n",
" if itr % 10 == 0:\n", " print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n",
" print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n", "# Calculate input state fidelity\n",
"\n", "fidelity_in = (3 * 0.7 + 1) / 4\n",
" # Calculate input state fidelity\n", "# Calculate output state fidelity\n",
" fidelity_in = (3 * 0.7 + 1) / 4\n", "fidelity = (len(status_fin) - loss) / len(status_fin)\n",
" # Calculate output state fidelity\n", "# Calculate successful rate\n",
" fidelity = (len(status_fin) - loss) / len(status_fin)\n", "suc_rate = sum([s.prob for s in status_fin])\n",
" # Calculate successful rate\n", "\n",
" suc_rate = sum([s.prob for s in status_fin])\n", "print(\"The fidelity of the input quantum state is:%.5f\" % fidelity_in)\n",
"\n", "print(\"The fidelity of the purified quantum state is: %.5f\" % fidelity.numpy()[0])\n",
" print(\"The fidelity of the input quantum state is:%.5f\" % fidelity_in)\n", "print(\"The probability of successful purification is:%.5f\" % suc_rate.numpy()[0])\n",
" print(\"The fidelity of the purified quantum state is: %.5f\" % fidelity.numpy()[0])\n", "rho_out = status_fin[0].state.numpy()\n",
" print(\"The probability of successful purification is:%.5f\" % suc_rate.numpy()[0])\n", "print(\"========================================================\")\n",
" rho_out = status_fin[0].state.numpy()\n", "print(f\"The output state is:\\n {np.around(rho_out, 4)}\")\n",
" print(\"========================================================\")\n", "print(f\"The initial logarithmic negativity is: {logarithmic_negativity(isotropic_state(2, 0.7))}\")\n",
" print(f\"The output state is:\\n {np.around(rho_out, 4)}\")\n", "print(f\"The final logarithmic negativity is: {logarithmic_negativity(rho_out)}\")"
" print(f\"The initial logarithmic negativity is: {logarithmic_negativity(isotropic_state(2, 0.7))}\")\n",
" print(f\"The final logarithmic negativity is: {logarithmic_negativity(rho_out)}\")"
] ]
}, },
{ {
...@@ -336,7 +333,7 @@ ...@@ -336,7 +333,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
...@@ -350,6 +347,35 @@ ...@@ -350,6 +347,35 @@
"toc_position": {}, "toc_position": {},
"toc_section_display": true, "toc_section_display": true,
"toc_window_display": false "toc_window_display": false
},
"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
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
"source": [ "source": [
"## 概述\n", "## 概述\n",
"\n", "\n",
"量子纠缠在量子通信、量子计算以及其他量子技术中是一种很重要的资源。因此,能否在这些领域构建出实际的应用,很大程度上取决于我们能否有效地利用量子纠缠这一资源。在 NISQ (Noisy Intermediate-Scale Quantum)时代,通过量子网络实现两个节点之间直接通讯量子信息是一项艰巨的任务。所以在当前阶段,通过本地操作和经典通讯(LOCC)[1] 来完成特定任务,是比全局操作(Global Operation)更为有效的方式。所谓本地操作和经典通讯,是指几个空间上分离的参与者只能在自己的实验室中执行本地操作,然后通过经典通讯的方式传递他们经典信息(可以是测量结果)。然而,设计 LOCC 协议来进行纠缠操作以及分布式量子信息处理是非常具有挑战性的,因为 LOCC 的结构通常很复杂并且很难用数学方法描述。为了更好地探索如何在近期量子设备上利用量子纠缠资源以及从长远角度来看进行分布式量子信息处理,我们设计了 **LOCCNet**,一种用于 LOCC 协议设计的机器学习框架。" "量子纠缠在量子通信、量子计算以及其他量子技术中是一种很重要的资源。因此,能否在这些领域构建出实际的应用,很大程度上取决于我们能否有效地利用量子纠缠这一资源。在 NISQ (Noisy Intermediate-Scale Quantum)时代,通过量子网络实现两个节点之间直接通讯量子信息是一项艰巨的任务。所以在当前阶段,通过本地操作和经典通讯(LOCC)[1] 来完成特定任务,是比全局操作(Global Operation)更为有效的方式。所谓本地操作和经典通讯,是指几个空间上分离的参与者只能在自己的实验室中执行本地操作,然后通过经典通讯的方式传递他们经典信息(可以是测量结果)。然而,设计 LOCC 协议来进行纠缠操作以及分布式量子信息处理是非常具有挑战性的,因为 LOCC 的结构通常很复杂并且很难用数学方法描述。为了更好地探索如何在近期量子设备上利用量子纠缠资源以及从长远角度来看进行分布式量子信息处理,我们设计了 **LOCCNet**,一种用于 LOCC 协议设计的机器学习框架 [2]。"
] ]
}, },
{ {
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
"source": [ "source": [
"## 什么是 LOCC?\n", "## 什么是 LOCC?\n",
"\n", "\n",
"正如上面所描述的,LOCC 指代的是本地操作和经典通讯(Local Operations and Classical Communication),即一个多量子比特系统分配给位于不同位置的多个实验室(参与方)。假如有 $N$ 实验室,每个实验室只能做对他们手中的子系统 $k \\in [1,\\cdots,N]$ 做量子操作 $\\{\\mathcal{E}^{(k)}_j\\}_{j=0}^{r}$。这些实验室之间允许传输包括测量结果在内的经典信息。LOCC 协议通常是根据通讯的轮数 $r$ 和实验室的数量 $N$ 进行分类的,记为 LOCC$_r(N)$。比如量子隐形传态协议 [2] 就是一个一轮通讯两个参与方的协议 LOCC$_1(2)$,参与的两方通常命名为 Alice 和 Bob。这个协议的任务是把一个未知的量子态 $\\lvert\\psi\\rangle$ 从 Alice 传输给 Bob,图 1 所示的流程图具体阐述了如何实现这一任务。\n", "正如上面所描述的,LOCC 指代的是本地操作和经典通讯(Local Operations and Classical Communication),即一个多量子比特系统分配给位于不同位置的多个实验室(参与方)。假如有 $N$ 实验室,每个实验室只能做对他们手中的子系统 $k \\in [1,\\cdots,N]$ 做量子操作 $\\{\\mathcal{E}^{(k)}_j\\}_{j=0}^{r}$。这些实验室之间允许传输包括测量结果在内的经典信息。LOCC 协议通常是根据通讯的轮数 $r$ 和实验室的数量 $N$ 进行分类的,记为 LOCC$_r(N)$。比如量子隐形传态协议 [3] 就是一个一轮通讯两个参与方的协议 LOCC$_1(2)$,参与的两方通常命名为 Alice 和 Bob。这个协议的任务是把一个未知的量子态 $\\lvert\\psi\\rangle$ 从 Alice 传输给 Bob,图 1 所示的流程图具体阐述了如何实现这一任务。\n",
"\n", "\n",
"\n", "\n",
"<img src=\"figures/teleportation-fig-circuit.jpg\" width=\"52%\" align = \"left\"/></center> <center><img src=\"figures/LOCC-fig-controltree.png\" width=\"48%\" align = \"right\"/> &nbsp; \n", "<img src=\"figures/teleportation-fig-circuit.jpg\" width=\"52%\" align = \"left\"/></center> <center><img src=\"figures/LOCC-fig-controltree.png\" width=\"48%\" align = \"right\"/> &nbsp; \n",
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
"<div style=\"text-align:center\">图 2:BBPSSW 蒸馏协议是一种 Cooperation-Type LOCC 协议。左图是电路图,右图是树状图,$m_1^{(1)}, m_1^{(2)} \\in \\{0,1\\}$,$m_j^{(k)}$ 表示的是第 $k^\\text{th}$ 参与方的测量结果。当测量结果为 $m_1^{(1)}m_1^{(2)} \\in \\{01,10\\}$ 时,判定协议失败。特别地,这里的本地操作为 $\\mathcal{E}_{0}^{(1)} = \\mathcal{E}_{0}^{(2)} = \\text{CNOT}$ 和 $\\mathcal{E}_{1}^{(1)} = \\mathcal{E}_{1}^{(2)} = I$。</div>\n", "<div style=\"text-align:center\">图 2:BBPSSW 蒸馏协议是一种 Cooperation-Type LOCC 协议。左图是电路图,右图是树状图,$m_1^{(1)}, m_1^{(2)} \\in \\{0,1\\}$,$m_j^{(k)}$ 表示的是第 $k^\\text{th}$ 参与方的测量结果。当测量结果为 $m_1^{(1)}m_1^{(2)} \\in \\{01,10\\}$ 时,判定协议失败。特别地,这里的本地操作为 $\\mathcal{E}_{0}^{(1)} = \\mathcal{E}_{0}^{(2)} = \\text{CNOT}$ 和 $\\mathcal{E}_{1}^{(1)} = \\mathcal{E}_{1}^{(2)} = I$。</div>\n",
"\n", "\n",
" \n", " \n",
"这些协议看上去十分简单,但是当参与方增多而且通讯轮数变多时,想要找到每一个参与方的最优的本地操作就会变得十分困难。现在我们大致了解了为什么说设计一个 LOCC 协议是一项艰巨的任务。即使如此困难,仍有许多重要的 LOCC 协议被科学家提了出来,比如:纠缠蒸馏(Entanglement Distillation) [3-4],纠缠转换(Entanglement Swapping) [5-6] 等。\n" "这些协议看上去十分简单,但是当参与方增多而且通讯轮数变多时,想要找到每一个参与方的最优的本地操作就会变得十分困难。现在我们大致了解了为什么说设计一个 LOCC 协议是一项艰巨的任务。即使如此困难,仍有许多重要的 LOCC 协议被科学家提了出来,比如:纠缠蒸馏(Entanglement Distillation) [4-5],纠缠转换(Entanglement Swapping) [6-7] 等。\n"
] ]
}, },
{ {
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
"source": [ "source": [
"## LOCCNet 的设计理念\n", "## LOCCNet 的设计理念\n",
"\n", "\n",
"我们从机器学习解决量子多体问题 [7] 以及预测蛋白质折叠结构 [8] 受到启发,使用机器学习的方法从众多可能的结果中搜寻最优的 LOCC 协议。为了实现上述目标,我们利用量子神经网络(Quantum Neural Networks, QNN)表示每个本地操作 $\\mathcal{E}^{(k)}_j$,这也就意味着树状图中的每个节点都代表着一个量子神经网络(QNN),也可以称为参数化量子电路(Parameterized Quantum circuit, PQC)$U(\\boldsymbol \\theta)$。在 Paddle Quantum 中,我们提供多种 QNN 模板以减少用户的学习成本。在设置 QNN 之后,我们便可以规划如何测量和通讯。下面需要做的就是学习目标函数,通常情况下,我们把目标函数编码成损失函数 $L$。举个例子,在量子隐形传态协议中,我们的学习目标是最大化 Alice 想要传输的态 $|\\psi\\rangle$ 和 Bob 最终得到的态 $|\\phi\\rangle$ 之间的保真度,也就是说 $L \\equiv \\sum_{m_1m_2} \\big(1- F(|\\psi\\rangle, |\\phi\\rangle)\\big)$。根据所处理的任务不同,损失函数会有相应的变化。最后一步,使用经典的优化方法(主要是梯度下降)来训练 QNN 中的参数。优化完成后,我们就获得了一个近似最优的 LOCC 协议。从使用者的角度来说,LOCCNet 这样一个框架可以极大地减少设计 LOCC 协议所用的时间,而且得到的协议也是很容易被实验验证。\n", "我们从机器学习解决量子多体问题 [8] 以及预测蛋白质折叠结构 [9] 受到启发,使用机器学习的方法从众多可能的结果中搜寻最优的 LOCC 协议。为了实现上述目标,我们利用量子神经网络(Quantum Neural Networks, QNN)表示每个本地操作 $\\mathcal{E}^{(k)}_j$,这也就意味着树状图中的每个节点都代表着一个量子神经网络(QNN),也可以称为参数化量子电路(Parameterized Quantum circuit, PQC)$U(\\boldsymbol \\theta)$。在 Paddle Quantum 中,我们提供多种 QNN 模板以减少用户的学习成本。在设置 QNN 之后,我们便可以规划如何测量和通讯。下面需要做的就是学习目标函数,通常情况下,我们把目标函数编码成损失函数 $L$。举个例子,在量子隐形传态协议中,我们的学习目标是最大化 Alice 想要传输的态 $|\\psi\\rangle$ 和 Bob 最终得到的态 $|\\phi\\rangle$ 之间的保真度,也就是说 $L \\equiv \\sum_{m_1m_2} \\big(1- F(|\\psi\\rangle, |\\phi\\rangle)\\big)$。根据所处理的任务不同,损失函数会有相应的变化。最后一步,使用经典的优化方法(主要是梯度下降)来训练 QNN 中的参数。优化完成后,我们就获得了一个近似最优的 LOCC 协议。从使用者的角度来说,LOCCNet 这样一个框架可以极大地减少设计 LOCC 协议所用的时间,而且得到的协议也是很容易被实验验证。\n",
"\n", "\n",
"\n", "\n",
"**注释:** 当前版本下,LOCCNet 仅支持密度矩阵形式。" "**注释:** 当前版本下,LOCCNet 仅支持密度矩阵形式。"
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
"\n", "\n",
"- `self.add_new_party(qubits_number, party_name=None)` 是用于添加一个新的参与方的函数,第一个参数代表该参与方有几个量子比特;第二个参数是可选参数,代表着参与者的名字。在协议中,我们可以选择是用过名字来指定参与方,也可以选择用编号来指定。如果我们希望使用名字,那么只需要在 `add_new_party` 函数中给 `party_name` 命名;如果希望使用编号,那么我们就不用给第二个参数赋值,第一个参与方会自动编号为 0,每增加一个参与方,其编号都会加一,同时该函数会将所添加的 party 的 ID 返回,其值根据定义会是 `int` 或者 `str`。\n", "- `self.add_new_party(qubits_number, party_name=None)` 是用于添加一个新的参与方的函数,第一个参数代表该参与方有几个量子比特;第二个参数是可选参数,代表着参与者的名字。在协议中,我们可以选择是用过名字来指定参与方,也可以选择用编号来指定。如果我们希望使用名字,那么只需要在 `add_new_party` 函数中给 `party_name` 命名;如果希望使用编号,那么我们就不用给第二个参数赋值,第一个参与方会自动编号为 0,每增加一个参与方,其编号都会加一,同时该函数会将所添加的 party 的 ID 返回,其值根据定义会是 `int` 或者 `str`。\n",
"\n", "\n",
"- `self.set_init_status(state, which_qubits)` 是用于设置协议的初始态的函数。第一个参数 `state` 是量子态,必须是密度矩阵的形式;第二个参数 `which_qubits` 是定位量子比特(哪一参与方的第几个量子比特,如 `(\"Alice\", 0)`)。需要说明的是,我们必须初始化所有的量子比特,否则程序将出现错误。" "- `self.set_init_state(state, which_qubits)` 是用于设置协议的初始态的函数。第一个参数 `state` 是量子态,必须是密度矩阵的形式;第二个参数 `which_qubits` 是定位量子比特(哪一参与方的第几个量子比特,如 `(\"Alice\", 0)`)。需要说明的是,我们必须初始化所有的量子比特,否则程序将出现错误。"
] ]
}, },
{ {
...@@ -142,21 +142,21 @@ ...@@ -142,21 +142,21 @@
"\n", "\n",
"[1] Chitambar, Eric, et al. \"Everything you always wanted to know about LOCC (but were afraid to ask).\" [Communications in Mathematical Physics 328.1 (2014): 303-326.](https://link.springer.com/article/10.1007/s00220-014-1953-9)\n", "[1] Chitambar, Eric, et al. \"Everything you always wanted to know about LOCC (but were afraid to ask).\" [Communications in Mathematical Physics 328.1 (2014): 303-326.](https://link.springer.com/article/10.1007/s00220-014-1953-9)\n",
"\n", "\n",
"[2] Bennett, Charles H., et al. \"Teleporting an unknown quantum state via dual classical and Einstein-Podolsky-Rosen channels.\" [Physical Review Letters 70.13 (1993): 1895.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.70.1895)\n", "[2] Zhao, Xuanqiang, et al. \"LOCCNet: a machine learning framework for distributed quantum information processing.\" [arXiv:2101.12190 (2021).](https://arxiv.org/abs/2101.12190)\n",
"\n", "\n",
"[3] Bennett, Charles H., et al. \"Purification of noisy entanglement and faithful teleportation via noisy channels.\" [Physical Review Letters 76.5 (1996): 722.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.76.722)\n", "[3] Bennett, Charles H., et al. \"Teleporting an unknown quantum state via dual classical and Einstein-Podolsky-Rosen channels.\" [Physical Review Letters 70.13 (1993): 1895.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.70.1895)\n",
"\n", "\n",
"[4] Deutsch, David, et al. \"Quantum privacy amplification and the security of quantum cryptography over noisy channels.\" [Physical Review Letters 77.13 (1996): 2818.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.77.2818)\n", "[4] Bennett, Charles H., et al. \"Purification of noisy entanglement and faithful teleportation via noisy channels.\" [Physical Review Letters 76.5 (1996): 722.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.76.722)\n",
"\n", "\n",
"[5] Zeilinger, Anton, et al. \"Three-particle entanglements from two entangled pairs.\" [Physical Review Letters 78.16 (1997): 3031.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.78.3031)\n", "[5] Deutsch, David, et al. \"Quantum privacy amplification and the security of quantum cryptography over noisy channels.\" [Physical Review Letters 77.13 (1996): 2818.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.77.2818)\n",
"\n", "\n",
"[6] Zukowski, Marek, et al. \"\" Event-ready-detectors\" Bell experiment via entanglement swapping.\" [Physical Review Letters 71.26 (1993).](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.71.4287)\n", "[6] Zeilinger, Anton, et al. \"Three-particle entanglements from two entangled pairs.\" [Physical Review Letters 78.16 (1997): 3031.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.78.3031)\n",
"\n", "\n",
"[7] Carleo, Giuseppe, and Matthias Troyer. \"Solving the quantum many-body problem with artificial neural networks.\" [Science 355.6325 (2017): 602-606.](https://science.sciencemag.org/content/355/6325/602)\n", "[7] Zukowski, Marek, et al. \"\" Event-ready-detectors\" Bell experiment via entanglement swapping.\" [Physical Review Letters 71.26 (1993).](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.71.4287)\n",
"\n", "\n",
"[8] Senior, Andrew W., et al. \"Improved protein structure prediction using potentials from deep learning.\" [Nature 577.7792 (2020): 706-710.](https://www.nature.com/articles/s41586-019-1923-7)\n", "[8] Carleo, Giuseppe, and Matthias Troyer. \"Solving the quantum many-body problem with artificial neural networks.\" [Science 355.6325 (2017): 602-606.](https://science.sciencemag.org/content/355/6325/602)\n",
"\n", "\n",
"\n" "[9] Senior, Andrew W., et al. \"Improved protein structure prediction using potentials from deep learning.\" [Nature 577.7792 (2020): 706-710.](https://www.nature.com/articles/s41586-019-1923-7)"
] ]
} }
], ],
...@@ -176,7 +176,7 @@ ...@@ -176,7 +176,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
"source": [ "source": [
"## Overview\n", "## Overview\n",
"\n", "\n",
"Quantum entanglement is an essential physical resource for quantum communication, quantum computation, and many other quantum technologies. Therefore, the ability to manipulate quantum entanglement reliably is an essential task if we want to build real applications in those fields. In the Noisy Intermediate-Scale Quantum (NISQ) era, directly transferring quantum information between the communication nodes inside a quantum network is an arduous task. Hence, the most natural set of operations to manipulate entanglement at this stage is the so-called Local Operations and Classical Communication (LOCC) [1] instead of global operations. Under this setup, several spatially separated parties can only implement local operations in their own labs and later communicates their measurement results (classical information) through a classical channel. Still, it is very challenging to design LOCC protocols for entanglement manipulation and further distributed quantum information processing tasks since the structure of LOCC is in general complicated and hard to characterize mathematically. To better explore the possibilities of near-term entanglement manipulation and long-term quantum information processing, we introduce **LOCCNet**, a machine learning framework for LOCC protocol design. \n" "Quantum entanglement is an essential physical resource for quantum communication, quantum computation, and many other quantum technologies. Therefore, the ability to manipulate quantum entanglement reliably is an essential task if we want to build real applications in those fields. In the Noisy Intermediate-Scale Quantum (NISQ) era, directly transferring quantum information between the communication nodes inside a quantum network is an arduous task. Hence, the most natural set of operations to manipulate entanglement at this stage is the so-called Local Operations and Classical Communication (LOCC) [1] instead of global operations. Under this setup, several spatially separated parties can only implement local operations in their own labs and later communicates their measurement results (classical information) through a classical channel. Still, it is very challenging to design LOCC protocols for entanglement manipulation and further distributed quantum information processing tasks since the structure of LOCC is in general complicated and hard to characterize mathematically. To better explore the possibilities of near-term entanglement manipulation and long-term quantum information processing, we introduce **LOCCNet**, a machine learning framework for LOCC protocol design [2]."
] ]
}, },
{ {
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
"source": [ "source": [
"## What is LOCC?\n", "## What is LOCC?\n",
"\n", "\n",
"As we explained above, LOCC stands for Local Operations and Classical Communication. It is also known as the \"distant lab\" paradigm, where a multipartite quantum system is distributed to some spatially separated labs. Suppose there are $N$ labs involved, and each lab is allowed to implement a sequence of quantum operations $\\{\\mathcal{E}^{(k)}_j\\}_{j=0}^{r}$ with respect to their own subsystems $k \\in [1,\\cdots,N]$. These labs are allowed to communicate any classical data including all the measurement results. A general LOCC protocol can be categorized according to the communication rounds $r$ applied and the number of distant labs involved, denoted as LOCC$_r(N)$, and pictorially described by a tree graph. For example, the famous quantum teleportation protocol [2] belongs to the 1-round LOCC$_1(2)$ family where only two parties are involved (Alice and Bob). The basic idea is to transfer an unknown quantum state $|\\psi\\rangle$ from Alice to Bob and the workflow is summarized in Figure 1,\n", "As we explained above, LOCC stands for Local Operations and Classical Communication. It is also known as the \"distant lab\" paradigm, where a multipartite quantum system is distributed to some spatially separated labs. Suppose there are $N$ labs involved, and each lab is allowed to implement a sequence of quantum operations $\\{\\mathcal{E}^{(k)}_j\\}_{j=0}^{r}$ with respect to their own subsystems $k \\in [1,\\cdots,N]$. These labs are allowed to communicate any classical data including all the measurement results. A general LOCC protocol can be categorized according to the communication rounds $r$ applied and the number of distant labs involved, denoted as LOCC$_r(N)$, and pictorially described by a tree graph. For example, the famous quantum teleportation protocol [3] belongs to the 1-round LOCC$_1(2)$ family where only two parties are involved (Alice and Bob). The basic idea is to transfer an unknown quantum state $|\\psi\\rangle$ from Alice to Bob and the workflow is summarized in Figure 1,\n",
"\n", "\n",
"\n", "\n",
"<img src=\"figures/teleportation-fig-circuit.jpg\" width=\"52%\" align = \"left\"/></center> <center><img src=\"figures/LOCC-fig-controltree.png\" width=\"48%\" align = \"right\"/> &nbsp; \n", "<img src=\"figures/teleportation-fig-circuit.jpg\" width=\"52%\" align = \"left\"/></center> <center><img src=\"figures/LOCC-fig-controltree.png\" width=\"48%\" align = \"right\"/> &nbsp; \n",
...@@ -38,8 +38,7 @@ ...@@ -38,8 +38,7 @@
"\n", "\n",
" \n", " \n",
" \n", " \n",
"These protocols look quite simple, but things could become extremely complicated when many parties communicate with each other for multiple rounds and we still need to find out the best local operations each party should apply in each round. Now, we should at least have a taste of why designing an LOCC protocol is challenging. With such difficulty, many practical LOCC protocols have been purposed to fulfill meaningful tasks including entanglement distillation [3-4], entanglement swapping [5-6], and so on.\n", "These protocols look quite simple, but things could become extremely complicated when many parties communicate with each other for multiple rounds and we still need to find out the best local operations each party should apply in each round. Now, we should at least have a taste of why designing an LOCC protocol is challenging. With such difficulty, many practical LOCC protocols have been purposed to fulfill meaningful tasks including entanglement distillation [4-5], entanglement swapping [6-7], and so on."
"\n"
] ]
}, },
{ {
...@@ -48,7 +47,7 @@ ...@@ -48,7 +47,7 @@
"source": [ "source": [
"## Philosophy of LOCCNet\n", "## Philosophy of LOCCNet\n",
"\n", "\n",
"Inspired by the success of Machine Learning (ML) in solving the quantum many-body problem [7] and protein folding structure prediction [8], we would like to adopt the learning capability of ML to help search optimal LOCC protocols among many possible combinations. The basic idea of LOCCNet is to utilize quantum neural networks (QNNs) to represent each local quantum operation $\\mathcal{E}^{(k)}_j$. That means each node represented in the tree graph of an LOCC protocol is now replaced by a QNN, which is essentially a parametrize quantum circuit (PQC) denoted by $U(\\boldsymbol \\theta)$. In Paddle Quantum, we already provide many QNN templates to reduce the learning cost for users. Once we set up the QNN, we can freely choose the measurement and communication plan. One last recipe we would need is a learning objective which is usually encoded as a loss function $L$. For example in quantum teleportation, the learning objective could be maximizing the state fidelity between Alice's state $|\\psi\\rangle$ and the state Bob receives $|\\phi\\rangle$ under four possible measurement results, meaning that $L \\equiv \\sum_{m_1m_2} \\big(1- F(|\\psi\\rangle, |\\phi\\rangle)\\big)$. The loss function should be designed according to the specific goal we want to accomplish. Finally, classical optimization methods (mainly gradient-based) will be applied to train the parameters in each QNN. Once the optimization has been done, we could obtain a near-optimal LOCC protocol. From our perspective, such a framework could sharply reduce the efforts to develop novel LOCC protocols, and the results should be easy to verify by experiments.\n", "Inspired by the success of Machine Learning (ML) in solving the quantum many-body problem [8] and protein folding structure prediction [9], we would like to adopt the learning capability of ML to help search optimal LOCC protocols among many possible combinations. The basic idea of LOCCNet is to utilize quantum neural networks (QNNs) to represent each local quantum operation $\\mathcal{E}^{(k)}_j$. That means each node represented in the tree graph of an LOCC protocol is now replaced by a QNN, which is essentially a parametrize quantum circuit (PQC) denoted by $U(\\boldsymbol \\theta)$. In Paddle Quantum, we already provide many QNN templates to reduce the learning cost for users. Once we set up the QNN, we can freely choose the measurement and communication plan. One last recipe we would need is a learning objective which is usually encoded as a loss function $L$. For example in quantum teleportation, the learning objective could be maximizing the state fidelity between Alice's state $|\\psi\\rangle$ and the state Bob receives $|\\phi\\rangle$ under four possible measurement results, meaning that $L \\equiv \\sum_{m_1m_2} \\big(1- F(|\\psi\\rangle, |\\phi\\rangle)\\big)$. The loss function should be designed according to the specific goal we want to accomplish. Finally, classical optimization methods (mainly gradient-based) will be applied to train the parameters in each QNN. Once the optimization has been done, we could obtain a near-optimal LOCC protocol. From our perspective, such a framework could sharply reduce the efforts to develop novel LOCC protocols, and the results should be easy to verify by experiments.\n",
"\n", "\n",
"\n", "\n",
"**Note:** LOCCNet only supports density matrix formulation at the current version." "**Note:** LOCCNet only supports density matrix formulation at the current version."
...@@ -88,7 +87,7 @@ ...@@ -88,7 +87,7 @@
"\n", "\n",
"- `self.add_new_party(qubits_number, party_name=None)` is used to add one party, the first parameter means the number of qubits held by this party; the second parameter is optional, which stands for the party's name. In a protocol, you can choose to identify each party either by their name character ID or a number ID. If you want to use the mode of character, you need to specify `party_name` when calling `add_new_party`; if you choose the latter mode, you don't need to set them, and the numbers will increase from 0 in the order you add them.\n", "- `self.add_new_party(qubits_number, party_name=None)` is used to add one party, the first parameter means the number of qubits held by this party; the second parameter is optional, which stands for the party's name. In a protocol, you can choose to identify each party either by their name character ID or a number ID. If you want to use the mode of character, you need to specify `party_name` when calling `add_new_party`; if you choose the latter mode, you don't need to set them, and the numbers will increase from 0 in the order you add them.\n",
"\n", "\n",
"- `self.set_init_status(state, which_qubits)` is used to set the initial quantum state to be processed by your protocol. Here `state` is always in density matrix formulation, and `which_qubits` represents the identification of quantum states (belong to which qubits held by certain parties). It should be noted that you must give all the qubits to the initial quantum state through this function. Otherwise, the program will occur unexpected errors." "- `self.set_init_state(state, which_qubits)` is used to set the initial quantum state to be processed by your protocol. Here `state` is always in density matrix formulation, and `which_qubits` represents the identification of quantum states (belong to which qubits held by certain parties). It should be noted that you must give all the qubits to the initial quantum state through this function. Otherwise, the program will occur unexpected errors."
] ]
}, },
{ {
...@@ -134,22 +133,21 @@ ...@@ -134,22 +133,21 @@
"\n", "\n",
"[1] Chitambar, Eric, et al. \"Everything you always wanted to know about LOCC (but were afraid to ask).\" [Communications in Mathematical Physics 328.1 (2014): 303-326.](https://link.springer.com/article/10.1007/s00220-014-1953-9)\n", "[1] Chitambar, Eric, et al. \"Everything you always wanted to know about LOCC (but were afraid to ask).\" [Communications in Mathematical Physics 328.1 (2014): 303-326.](https://link.springer.com/article/10.1007/s00220-014-1953-9)\n",
"\n", "\n",
"[2] Bennett, Charles H., et al. \"Teleporting an unknown quantum state via dual classical and Einstein-Podolsky-Rosen channels.\" [Physical Review Letters 70.13 (1993): 1895.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.70.1895)\n", "[2] Zhao, Xuanqiang, et al. \"LOCCNet: a machine learning framework for distributed quantum information processing.\" [arXiv:2101.12190 (2021).](https://arxiv.org/abs/2101.12190)\n",
"\n", "\n",
"[3] Bennett, Charles H., et al. \"Purification of noisy entanglement and faithful teleportation via noisy channels.\" [Physical Review Letters 76.5 (1996): 722.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.76.722)\n", "[3] Bennett, Charles H., et al. \"Teleporting an unknown quantum state via dual classical and Einstein-Podolsky-Rosen channels.\" [Physical Review Letters 70.13 (1993): 1895.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.70.1895)\n",
"\n", "\n",
"[4] Deutsch, David, et al. \"Quantum privacy amplification and the security of quantum cryptography over noisy channels.\" [Physical Review Letters 77.13 (1996): 2818.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.77.2818)\n", "[4] Bennett, Charles H., et al. \"Purification of noisy entanglement and faithful teleportation via noisy channels.\" [Physical Review Letters 76.5 (1996): 722.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.76.722)\n",
"\n", "\n",
"[5] Zeilinger, Anton, et al. \"Three-particle entanglements from two entangled pairs.\" [Physical Review Letters 78.16 (1997): 3031.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.78.3031)\n", "[5] Deutsch, David, et al. \"Quantum privacy amplification and the security of quantum cryptography over noisy channels.\" [Physical Review Letters 77.13 (1996): 2818.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.77.2818)\n",
"\n", "\n",
"[6] Zukowski, Marek, et al. \"\" Event-ready-detectors\" Bell experiment via entanglement swapping.\" [Physical Review Letters 71.26 (1993).](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.71.4287)\n", "[6] Zeilinger, Anton, et al. \"Three-particle entanglements from two entangled pairs.\" [Physical Review Letters 78.16 (1997): 3031.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.78.3031)\n",
"\n", "\n",
"[7] Carleo, Giuseppe, and Matthias Troyer. \"Solving the quantum many-body problem with artificial neural networks.\" [Science 355.6325 (2017): 602-606.](https://science.sciencemag.org/content/355/6325/602)\n", "[7] Zukowski, Marek, et al. \"\" Event-ready-detectors\" Bell experiment via entanglement swapping.\" [Physical Review Letters 71.26 (1993).](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.71.4287)\n",
"\n", "\n",
"[8] Senior, Andrew W., et al. \"Improved protein structure prediction using potentials from deep learning.\" [Nature 577.7792 (2020): 706-710.](https://www.nature.com/articles/s41586-019-1923-7)\n", "[8] Carleo, Giuseppe, and Matthias Troyer. \"Solving the quantum many-body problem with artificial neural networks.\" [Science 355.6325 (2017): 602-606.](https://science.sciencemag.org/content/355/6325/602)\n",
"\n", "\n",
"\n", "[9] Senior, Andrew W., et al. \"Improved protein structure prediction using potentials from deep learning.\" [Nature 577.7792 (2020): 706-710.](https://www.nature.com/articles/s41586-019-1923-7)"
"\n"
] ]
} }
], ],
......
...@@ -26,12 +26,9 @@ ...@@ -26,12 +26,9 @@
"\n", "\n",
"量子隐形传态协议最初由 C. H. Bennett 等人在 1993 年提出 [1],并在 1997 年通过基于光子的实验平台进行了验证 [2-3]。其主要工作流程如下图所示。传输过程中需要 2 个通信节点或参与方,即 Alice 和 Bob。简单起见,我们仅考虑传输一个单量子比特的量子态 $|\\psi\\rangle_C$,这样整个系统总共需要 3 个量子比特,包括提前共享给 Alice 和 Bob 的最大纠缠态 $|\\Phi^+\\rangle_{AB} = \\frac{1}{\\sqrt{2}}(|00\\rangle + |11\\rangle)$。 Alice 持有量子比特 A 和 C, Bob 持有量子比特 B。**注释:量子隐形传态协议仅传输量子信息,而非在物理上直接传输量子比特。**\n", "量子隐形传态协议最初由 C. H. Bennett 等人在 1993 年提出 [1],并在 1997 年通过基于光子的实验平台进行了验证 [2-3]。其主要工作流程如下图所示。传输过程中需要 2 个通信节点或参与方,即 Alice 和 Bob。简单起见,我们仅考虑传输一个单量子比特的量子态 $|\\psi\\rangle_C$,这样整个系统总共需要 3 个量子比特,包括提前共享给 Alice 和 Bob 的最大纠缠态 $|\\Phi^+\\rangle_{AB} = \\frac{1}{\\sqrt{2}}(|00\\rangle + |11\\rangle)$。 Alice 持有量子比特 A 和 C, Bob 持有量子比特 B。**注释:量子隐形传态协议仅传输量子信息,而非在物理上直接传输量子比特。**\n",
"\n", "\n",
"\n", "![](figures/teleportation-fig-circuit.jpg \"图 1:量子隐形传态: 传输量子态 $|\\psi\\rangle$ 从 Alice 到 Bob\")\n",
"<center><img src=\"figures/teleportation-fig-circuit.jpg\" height=\"400\" width=\"600\"></center>\n",
"<div style=\"text-align:center\">图 1:量子隐形传态: 传输量子态 $|\\psi\\rangle$ 从 Alice 到 Bob </div>\n", "<div style=\"text-align:center\">图 1:量子隐形传态: 传输量子态 $|\\psi\\rangle$ 从 Alice 到 Bob </div>\n",
"\n", "\n",
"\n",
"\n",
"**步骤 I:** 一开始,整个量子系统的状态可以描述为\n", "**步骤 I:** 一开始,整个量子系统的状态可以描述为\n",
"\n", "\n",
"$$\n", "$$\n",
...@@ -89,16 +86,16 @@ ...@@ -89,16 +86,16 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T13:42:51.662130Z", "end_time": "2021-03-09T06:22:58.705389Z",
"start_time": "2021-01-26T13:42:45.290573Z" "start_time": "2021-03-09T06:22:55.030541Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle.fluid as fluid\n",
"from paddle_quantum.locc import LoccNet\n", "from paddle_quantum.locc import LoccNet\n",
"from paddle.complex import matmul, trace\n", "from paddle import matmul, trace\n",
"import paddle\n",
"from paddle_quantum.utils import state_fidelity\n", "from paddle_quantum.utils import state_fidelity\n",
"from paddle_quantum.state import bell_state, isotropic_state, density_op_random" "from paddle_quantum.state import bell_state, isotropic_state, density_op_random"
] ]
...@@ -115,8 +112,8 @@ ...@@ -115,8 +112,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T13:42:51.859178Z", "end_time": "2021-03-09T06:23:06.232030Z",
"start_time": "2021-01-26T13:42:51.666289Z" "start_time": "2021-03-09T06:23:06.179323Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -125,9 +122,6 @@ ...@@ -125,9 +122,6 @@
" def __init__(self):\n", " def __init__(self):\n",
" super(LOCC, self).__init__()\n", " super(LOCC, self).__init__()\n",
" \n", " \n",
" # 初始化 LOCCNet\n",
" self.parties = list()\n",
" \n",
" # 添加第一个参与方 Alice\n", " # 添加第一个参与方 Alice\n",
" # 第一个参数 2 代表着 Alice 手里有几个量子比特\n", " # 第一个参数 2 代表着 Alice 手里有几个量子比特\n",
" # 第二个参数代表着参与方的名字\n", " # 第二个参数代表着参与方的名字\n",
...@@ -140,21 +134,21 @@ ...@@ -140,21 +134,21 @@
" \n", " \n",
"\n", "\n",
" # 准备一个贝尔态\n", " # 准备一个贝尔态\n",
" _state = fluid.dygraph.to_variable(bell_state(2))\n", " _state = paddle.to_tensor(bell_state(2))\n",
"# _state = fluid.dygraph.to_variable(isotropic_state(2, 0.8))\n", " # _state = paddle.to_tensor(isotropic_state(2, 0.8))\n",
"\n", "\n",
" \n", " \n",
" # 随机制备传输用的纯态 (rank =1)\n", " # 随机制备传输用的纯态 (rank =1)\n",
" random_state = density_op_random(n=1, real_or_complex=2, rank=1)\n", " random_state = density_op_random(n=1, real_or_complex=2, rank=1)\n",
" self.state_C = fluid.dygraph.to_variable(random_state)\n", " self.state_C = paddle.to_tensor(random_state)\n",
" \n", " \n",
" # 通过分配上述制备好的量子态初始化整个量子系统\n", " # 通过分配上述制备好的量子态初始化整个量子系统\n",
" # 这里 (\"Alice\", 0) 即表示量子比特 C\n", " # 这里 (\"Alice\", 0) 即表示量子比特 C\n",
" # 这里 (\"Alice\", 1) 即表示量子比特 A\n", " # 这里 (\"Alice\", 1) 即表示量子比特 A\n",
" # 这里 (\"Bob\", 0) 即表示量子比特 B\n", " # 这里 (\"Bob\", 0) 即表示量子比特 B\n",
"# print('提前分配好的纠缠态为:\\n', _state.numpy())\n", " # print('提前分配好的纠缠态为:\\n', _state.numpy())\n",
" self.set_init_status(self.state_C, [(\"Alice\", 0)])\n", " self.set_init_state(self.state_C, [(\"Alice\", 0)])\n",
" self.set_init_status(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n", " self.set_init_state(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n",
"\n", "\n",
"\n", "\n",
" def teleportation(self):\n", " def teleportation(self):\n",
...@@ -236,11 +230,11 @@ ...@@ -236,11 +230,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T13:51:41.271853Z", "end_time": "2021-03-09T06:23:14.626278Z",
"start_time": "2021-01-26T13:51:20.136017Z" "start_time": "2021-03-09T06:23:08.646876Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -253,17 +247,15 @@ ...@@ -253,17 +247,15 @@
} }
], ],
"source": [ "source": [
"with fluid.dygraph.guard():\n", "SEED = 999 # 固定随机数\n",
" \n", "num_state = 200 # 设置随机态的生成数量\n",
" np.random.seed(999) # 固定生成传输态的随机种子\n", "list_fid = [] # 用于记录保真度\n",
" num_state = 200 # 设置随机态的生成数量\n", "np.random.seed(SEED)\n",
" list_fid = [] # 用于记录保真度\n", "# 开始采样 \n",
" \n", "for idx in range(num_state):\n",
" # 开始采样 \n", " list_fid.append(LOCC().teleportation())\n",
" for idx in range(num_state):\n", "\n",
" list_fid.append(LOCC().teleportation())\n", "print('平均保真度 =', np.around(sum(list_fid)/len(list_fid), 4), ', 标准差 =', np.std(list_fid))"
"\n",
" print('平均保真度 =', np.around(sum(list_fid)/len(list_fid), 4), ', 标准差 =', np.std(list_fid))"
] ]
}, },
{ {
...@@ -307,13 +299,9 @@ ...@@ -307,13 +299,9 @@
"6. 重复步骤 1-5,直到损失函数收敛。\n", "6. 重复步骤 1-5,直到损失函数收敛。\n",
"7. 生成一组随机的态 $\\{\\lvert\\psi_C\\rangle\\}$,并以平均保真度对训练出的传输协议进行基准测试。\n", "7. 生成一组随机的态 $\\{\\lvert\\psi_C\\rangle\\}$,并以平均保真度对训练出的传输协议进行基准测试。\n",
"\n", "\n",
"\n", "![](figures/teleportation-fig-LOCCNet.png \"图 2: 用 LOCCNet 学习量子隐形传态协议\")\n",
"\n",
"<center><img src=\"figures/teleportation-fig-LOCCNet.png\" height=\"400\" width=\"600\"></center>\n",
"<div style=\"text-align:center\">图 2: 用 LOCCNet 学习量子隐形传态协议 </div>\n", "<div style=\"text-align:center\">图 2: 用 LOCCNet 学习量子隐形传态协议 </div>\n",
"\n", "\n",
"\n",
"\n",
"**注释:** 为了确保训练出的 LOCC 协议对所有态均有效,我们将训练集设为 4 个线性独立态,即 $\\{|0\\rangle\\langle 0|,|1\\rangle\\langle 1|,|+\\rangle\\langle +|,|+\\rangle\\langle +|_y\\}$ 。其中 $|+\\rangle, |+\\rangle_y$ 分别为泡利 $X,Y$ 矩阵的正特征值对应的特征向量。 该训练集在密度矩阵的表示下为:\n", "**注释:** 为了确保训练出的 LOCC 协议对所有态均有效,我们将训练集设为 4 个线性独立态,即 $\\{|0\\rangle\\langle 0|,|1\\rangle\\langle 1|,|+\\rangle\\langle +|,|+\\rangle\\langle +|_y\\}$ 。其中 $|+\\rangle, |+\\rangle_y$ 分别为泡利 $X,Y$ 矩阵的正特征值对应的特征向量。 该训练集在密度矩阵的表示下为:\n",
"\n", "\n",
"$$\n", "$$\n",
...@@ -341,8 +329,13 @@ ...@@ -341,8 +329,13 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 6,
"metadata": {}, "metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:26:15.991221Z",
"start_time": "2021-03-09T06:26:15.937457Z"
}
},
"outputs": [], "outputs": [],
"source": [ "source": [
"class LOCC_Train(LoccNet):\n", "class LOCC_Train(LoccNet):\n",
...@@ -364,27 +357,25 @@ ...@@ -364,27 +357,25 @@
" \n", " \n",
"\n", "\n",
" # 准备一个贝尔态\n", " # 准备一个贝尔态\n",
" _state = fluid.dygraph.to_variable(bell_state(2))\n", " _state = paddle.to_tensor(bell_state(2))\n",
"# _state = fluid.dygraph.to_variable(isotropic_state(2, 0.8))\n", " # _state = paddle.to_tensor(isotropic_state(2, 0.8))\n",
"\n", "\n",
"\n", "\n",
" # 设置 Alice 本地操作的参数\n", " # 设置 Alice 本地操作的参数\n",
" self.theta_A = self.create_parameter(shape=[15], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, \n", " self.theta_A = self.create_parameter(shape=[15], default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n",
" seed=SEED), dtype=\"float64\")\n",
" # 设置 Bob 本地操作的参数\n", " # 设置 Bob 本地操作的参数\n",
" self.theta_B = self.create_parameter(shape=[4, 3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, \n", " self.theta_B = self.create_parameter(shape=[4, 3], default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n",
" seed=SEED), dtype=\"float64\")\n",
"\n", "\n",
" # 训练集: 4 个线性独立态\n", " # 训练集: 4 个线性独立态\n",
" _state0 = fluid.dygraph.to_variable(np.array([[1, 0], [0, 0]], dtype=np.complex128))\n", " _state0 = paddle.to_tensor(np.array([[1, 0], [0, 0]], dtype=np.complex128))\n",
" _state1 = fluid.dygraph.to_variable(np.array([[0, 0], [0, 1]], dtype=np.complex128))\n", " _state1 = paddle.to_tensor(np.array([[0, 0], [0, 1]], dtype=np.complex128))\n",
" _state2 = fluid.dygraph.to_variable(np.array([[0.5, 0.5], [0.5, 0.5]], dtype=np.complex128))\n", " _state2 = paddle.to_tensor(np.array([[0.5, 0.5], [0.5, 0.5]], dtype=np.complex128))\n",
" _state3 = fluid.dygraph.to_variable(np.array([[0.5, -0.5j], [0.5j, 0.5]], dtype=np.complex128))\n", " _state3 = paddle.to_tensor(np.array([[0.5, -0.5j], [0.5j, 0.5]], dtype=np.complex128))\n",
" self.init_states = [_state0, _state1, _state2, _state3]\n", " self.init_states = [_state0, _state1, _state2, _state3]\n",
"\n", "\n",
" # 通过分配上述制备好的量子态初始化整个量子系统\n", " # 通过分配上述制备好的量子态初始化整个量子系统\n",
" self.set_init_status(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n", " self.set_init_state(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n",
" self.set_init_status(_state0, [(\"Alice\", 0)])\n", " self.set_init_state(_state0, [(\"Alice\", 0)])\n",
"\n", "\n",
" def LOCCNet(self):\n", " def LOCCNet(self):\n",
" \n", " \n",
...@@ -424,57 +415,84 @@ ...@@ -424,57 +415,84 @@
" status_fin = self.partial_state(status_B, [(\"Bob\", 0)])\n", " status_fin = self.partial_state(status_B, [(\"Bob\", 0)])\n",
" \n", " \n",
" # 将所有的测量结果的损失函数进行累加\n", " # 将所有的测量结果的损失函数进行累加\n",
" loss += 1 - trace(matmul(init_state, status_fin.state)).real[0]\n", " loss += 1 - paddle.real(trace(matmul(init_state, status_fin.state)))[0]\n",
" \n", " \n",
" return loss\n", " return loss\n",
"\n", "\n",
" # 存储训练结束后的最优参数\n", " # 存储训练结束后的最优参数\n",
" def save_module(self):\n", " def save_module(self):\n",
" theta = np.array([self.theta_A.numpy(), self.theta_B.numpy()])\n", " theta = np.array([self.theta_A.numpy(), self.theta_B.numpy()], dtype=\"object\")\n",
" np.save('parameters/QT_LOCCNet', theta)" " np.save('parameters/QT_LOCCNet', theta)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 7,
"metadata": {}, "metadata": {
"outputs": [], "ExecuteTime": {
"end_time": "2021-03-09T06:27:21.094741Z",
"start_time": "2021-03-09T06:26:16.291397Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"itr 0: 7.721435597307273\n",
"itr 10: 0.5636061774837096\n",
"itr 20: 0.20642802374795632\n",
"itr 30: 0.07340371172539029\n",
"itr 40: 0.025112969166681598\n",
"itr 50: 0.008655519545057166\n",
"itr 60: 0.0035853096929094885\n",
"itr 70: 0.0014441032202451298\n",
"itr 80: 0.0004540960989092291\n",
"itr 90: 0.00018530025729923683\n",
"itr 100: 4.679932743989479e-05\n",
"itr 110: 1.5186530775368468e-05\n",
"itr 120: 4.8322085606233856e-06\n",
"itr 130: 3.08099659207528e-06\n",
"itr 140: 1.0481638913484304e-06\n"
]
}
],
"source": [ "source": [
"ITR = 150 # 设置优化循环次数\n", "ITR = 150 # 设置优化循环次数\n",
"LR = 0.2 # 设置学习速率\n", "LR = 0.2 # 设置学习速率\n",
"SEED = 999 # 固定本地操作中参数的初始化随机数种子\n", "SEED = 999 # 固定本地操作中参数的初始化随机数种子\n",
"np.random.seed(SEED)\n",
"paddle.seed(SEED)\n",
"\n", "\n",
"# 初始化动态图模式\n", "\n",
"with fluid.dygraph.guard():\n", "net = LOCC_Train()\n",
"\n", "\n",
" net = LOCC_Train()\n", "# 选择 Adam 优化器\n",
" \n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters= net.parameters())\n",
" # 选择 Adam 优化器\n", "\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list= net.parameters())\n", "# 记录损失\n",
" \n", "loss_list = []\n",
" # 记录损失\n", "\n",
" loss_list = []\n", "# 开始优化循环\n",
" \n", "for itr in range(ITR):\n",
" # 开始优化循环\n", "\n",
" for itr in range(ITR):\n", " # 向前传播计算损失函数\n",
"\n", " loss = net.LOCCNet()\n",
" # 向前传播计算损失函数\n", "\n",
" loss = net.LOCCNet()\n", " # 反向传播优化损失函数\n",
" \n", " loss.backward()\n",
" # 反向传播优化损失函数\n", " opt.minimize(loss)\n",
" loss.backward()\n", "\n",
" opt.minimize(loss)\n", " # 清除梯度\n",
" \n", " opt.clear_grad()\n",
" # 清除梯度\n", "\n",
" net.clear_gradients()\n", " # 记录训练结果\n",
" \n", " loss_list.append(loss.numpy()[0])\n",
" # 记录训练结果\n", " if itr % 10 == 0:\n",
" loss_list.append(loss.numpy()[0])\n", " print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n",
" if itr % 10 == 0:\n", "\n",
" print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n", "# 保存参数\n",
" \n", "net.save_module()"
" # 保存参数\n",
" net.save_module()"
] ]
}, },
{ {
...@@ -488,11 +506,11 @@ ...@@ -488,11 +506,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T14:23:22.264769Z", "end_time": "2021-03-09T06:27:35.419952Z",
"start_time": "2021-01-26T14:23:22.072281Z" "start_time": "2021-03-09T06:27:35.391435Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -505,14 +523,14 @@ ...@@ -505,14 +523,14 @@
" self.add_new_party(2, party_name=\"Alice\")\n", " self.add_new_party(2, party_name=\"Alice\")\n",
" self.add_new_party(1, party_name=\"Bob\")\n", " self.add_new_party(1, party_name=\"Bob\")\n",
" \n", " \n",
" self.theta_A = fluid.dygraph.to_variable(para[0])\n", " self.theta_A = paddle.to_tensor(para[0])\n",
" self.theta_B = fluid.dygraph.to_variable(para[1])\n", " self.theta_B = paddle.to_tensor(para[1])\n",
" \n", " \n",
" _state = fluid.dygraph.to_variable(bell_state(2))\n", " _state = paddle.to_tensor(bell_state(2))\n",
" random_state = density_op_random(n=1)\n", " random_state = density_op_random(n=1)\n",
" self._state0 = fluid.dygraph.to_variable(random_state)\n", " self._state0 = paddle.to_tensor(random_state)\n",
" self.set_init_status(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n", " self.set_init_state(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n",
" self.set_init_status(self._state0, [(\"Alice\", 0)])\n", " self.set_init_state(self._state0, [(\"Alice\", 0)])\n",
" \n", " \n",
"\n", "\n",
" def benchmark(self):\n", " def benchmark(self):\n",
...@@ -538,11 +556,11 @@ ...@@ -538,11 +556,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 11,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-26T14:24:43.301269Z", "end_time": "2021-03-09T06:28:31.015666Z",
"start_time": "2021-01-26T14:24:11.028218Z" "start_time": "2021-03-09T06:28:18.203521Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -550,24 +568,24 @@ ...@@ -550,24 +568,24 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"平均保真度 = 1.0 , 标准差 = 5.695904177817817e-07\n" "平均保真度 = 1.0 , 标准差 = 5.695904176663085e-07\n"
] ]
} }
], ],
"source": [ "source": [
"with fluid.dygraph.guard():\n", "# 加载预先训练的电路参数\n",
"\n", "para = np.load('parameters/QT_LOCCNet_Trained.npy', allow_pickle=True)\n",
" # 加载预先训练的电路参数\n", "SEED = 999 # 固定生成传输态的随机种子\n",
" para = np.load('parameters/QT_LOCCNet_Trained.npy', allow_pickle=True)\n", "num_state = 200 # 设置随机态的生成数量\n",
" np.random.seed(999) # 固定生成传输态的随机种子\n", "list_fid = [] # 用于记录保真度\n",
" num_state = 200 # 设置随机态的生成数量\n", "np.random.seed(SEED)\n",
" list_fid = [] # 用于记录保真度\n", "paddle.seed(SEED)\n",
" \n", "\n",
" # 采样\n", "# 采样\n",
" for idx in range(num_state):\n", "for idx in range(num_state):\n",
" list_fid.append(LOCC_Test().benchmark())\n", " list_fid.append(LOCC_Test().benchmark())\n",
"\n", "\n",
" print('平均保真度 =', np.around(sum(list_fid)/len(list_fid), 4), ', 标准差 =', np.std(list_fid))" "print('平均保真度 =', np.around(sum(list_fid)/len(list_fid), 4), ', 标准差 =', np.std(list_fid))"
] ]
}, },
{ {
...@@ -613,7 +631,7 @@ ...@@ -613,7 +631,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -22,8 +22,7 @@ ...@@ -22,8 +22,7 @@
"\n", "\n",
"The original teleportation protocol was proposed by C. H. Bennett et al. in 1993 [1] and experimentally verified in 1997 with photonic platforms [2-3]. The workflow is illustrated in the figure below. Following the convention, this process requires 2 communication nodes or parties, namely $A$ (Alice) and $B$ (Bob). For simplicity, we only consider transferring a single-qubit quantum state $|\\psi\\rangle_C$ and this requires 3 qubits in total including the pre-shared maximally entangled state $|\\Phi^+\\rangle_{AB} = \\frac{1}{\\sqrt{2}}(|00\\rangle + |11\\rangle)$. Alice holds systems A and C,Bob holds system B. **Note: Only quantum information is transferred, not the physical qubits.** \n", "The original teleportation protocol was proposed by C. H. Bennett et al. in 1993 [1] and experimentally verified in 1997 with photonic platforms [2-3]. The workflow is illustrated in the figure below. Following the convention, this process requires 2 communication nodes or parties, namely $A$ (Alice) and $B$ (Bob). For simplicity, we only consider transferring a single-qubit quantum state $|\\psi\\rangle_C$ and this requires 3 qubits in total including the pre-shared maximally entangled state $|\\Phi^+\\rangle_{AB} = \\frac{1}{\\sqrt{2}}(|00\\rangle + |11\\rangle)$. Alice holds systems A and C,Bob holds system B. **Note: Only quantum information is transferred, not the physical qubits.** \n",
"\n", "\n",
"\n", "![teleportation](figures/teleportation-fig-circuit.jpg \"Figure 1: Quantum teleportation: Transferring quantum state $|\\psi\\rangle$ from Alice to receiver Bob.\")\n",
"<center><img src=\"figures/teleportation-fig-circuit.jpg\" height=\"400\" width=\"600\"></center>\n",
"<div style=\"text-align:center\">Figure 1: Quantum teleportation: Transferring quantum state $|\\psi\\rangle$ from Alice to receiver Bob. </div>\n" "<div style=\"text-align:center\">Figure 1: Quantum teleportation: Transferring quantum state $|\\psi\\rangle$ from Alice to receiver Bob. </div>\n"
] ]
}, },
...@@ -104,16 +103,16 @@ ...@@ -104,16 +103,16 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T08:58:58.723528Z", "end_time": "2021-03-09T06:28:54.132971Z",
"start_time": "2021-01-25T08:58:52.538986Z" "start_time": "2021-03-09T06:28:49.877088Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle.fluid as fluid\n",
"from paddle_quantum.locc import LoccNet\n", "from paddle_quantum.locc import LoccNet\n",
"from paddle.complex import matmul, trace\n", "from paddle import matmul, trace\n",
"import paddle\n",
"from paddle_quantum.utils import state_fidelity\n", "from paddle_quantum.utils import state_fidelity\n",
"from paddle_quantum.state import bell_state, isotropic_state, density_op_random" "from paddle_quantum.state import bell_state, isotropic_state, density_op_random"
] ]
...@@ -130,8 +129,8 @@ ...@@ -130,8 +129,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T08:58:58.778103Z", "end_time": "2021-03-09T06:28:54.197393Z",
"start_time": "2021-01-25T08:58:58.740654Z" "start_time": "2021-03-09T06:28:54.155480Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -140,9 +139,6 @@ ...@@ -140,9 +139,6 @@
" def __init__(self):\n", " def __init__(self):\n",
" super(LOCC, self).__init__()\n", " super(LOCC, self).__init__()\n",
" \n", " \n",
" # Initialize LOCCNet\n",
" self.parties = list()\n",
" \n",
" # Add the first party Alice \n", " # Add the first party Alice \n",
" # The first parameter 2 stands for how many qubits A holds\n", " # The first parameter 2 stands for how many qubits A holds\n",
" # The second parameter records the name of this qubit holder\n", " # The second parameter records the name of this qubit holder\n",
...@@ -155,21 +151,21 @@ ...@@ -155,21 +151,21 @@
" \n", " \n",
"\n", "\n",
" # Create a bell state\n", " # Create a bell state\n",
" _state = fluid.dygraph.to_variable(bell_state(2))\n", " _state = paddle.to_tensor(bell_state(2))\n",
"# _state = fluid.dygraph.to_variable(isotropic_state(2, 0.8))\n", " # _state = paddle.to_tensor(isotropic_state(2, 0.8))\n",
"\n", "\n",
" \n", " \n",
" # Generate random pure quantum states for teleportation\n", " # Generate random pure quantum states for teleportation\n",
" random_state = density_op_random(n=1, real_or_complex=2, rank=1)\n", " random_state = density_op_random(n=1, real_or_complex=2, rank=1)\n",
" self.state_C = fluid.dygraph.to_variable(random_state)\n", " self.state_C = paddle.to_tensor(random_state)\n",
" \n", " \n",
" # Initialize the system by distributing states between Alice and Bob\n", " # Initialize the system by distributing states between Alice and Bob\n",
" # (\"Alice\", 0) refers to qubit C\n", " # (\"Alice\", 0) refers to qubit C\n",
" # (\"Alice\", 1) refers to qubit A\n", " # (\"Alice\", 1) refers to qubit A\n",
" # (\"Bob\", 0) refers to qubit B\n", " # (\"Bob\", 0) refers to qubit B\n",
"# print('Pre-shared entanglement state is:\\n', _state.numpy())\n", " # print('Pre-shared entanglement state is:\\n', _state.numpy())\n",
" self.set_init_status(self.state_C, [(\"Alice\", 0)])\n", " self.set_init_state(self.state_C, [(\"Alice\", 0)])\n",
" self.set_init_status(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n", " self.set_init_state(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n",
"\n", "\n",
"\n", "\n",
" def teleportation(self):\n", " def teleportation(self):\n",
...@@ -253,8 +249,8 @@ ...@@ -253,8 +249,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T08:59:16.906737Z", "end_time": "2021-03-09T06:29:03.318794Z",
"start_time": "2021-01-25T08:58:58.817863Z" "start_time": "2021-03-09T06:28:54.202670Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -262,22 +258,20 @@ ...@@ -262,22 +258,20 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Teleportation_Fidelity_Avg: 1.0 , std= 1.0610206920288784e-14\n" "Teleportation_Fidelity_Avg: 1.0 , std= 6.429150606796583e-09\n"
] ]
} }
], ],
"source": [ "source": [
"with fluid.dygraph.guard():\n", "SEED = 999 # Fix random seed\n",
" \n", "num_state = 200 # Number of random states generated\n",
" np.random.seed(999) # Fix random seed\n", "list_fid = [] # Record the fidelity\n",
" num_state = 200 # Number of random states generated\n", "np.random.seed(SEED)\n",
" list_fid = [] # Record the fidelity\n", "# Start sampling\n",
" \n", "for idx in range(num_state):\n",
" # Start sampling\n", " list_fid.append(LOCC().teleportation())\n",
" for idx in range(num_state):\n", "\n",
" list_fid.append(LOCC().teleportation())\n", "print('Teleportation_Fidelity_Avg:', np.around(sum(list_fid)/len(list_fid), 4), ', std=', np.std(list_fid))"
"\n",
" print('Teleportation_Fidelity_Avg:', np.around(sum(list_fid)/len(list_fid), 4), ', std=', np.std(list_fid))"
] ]
}, },
{ {
...@@ -327,11 +321,9 @@ ...@@ -327,11 +321,9 @@
"6. Repeat steps 1-5 until the loss function converges to the global minimum.\n", "6. Repeat steps 1-5 until the loss function converges to the global minimum.\n",
"7. Generate an ensemble of arbitrary states $\\{\\lvert\\psi_C\\rangle\\}$, and benchmark the trained protocol with average state fidelity.\n", "7. Generate an ensemble of arbitrary states $\\{\\lvert\\psi_C\\rangle\\}$, and benchmark the trained protocol with average state fidelity.\n",
"\n", "\n",
"\n", "![teleportation-LOCCNet](figures/teleportation-fig-LOCCNet.png \"Figure 2: Learning a teleportation protocol with LOCCNet.\")\n",
"<center><img src=\"figures/teleportation-fig-LOCCNet.png\" height=\"400\" width=\"600\"></center>\n",
"<div style=\"text-align:center\">Figure 2: Learning a teleportation protocol with LOCCNet. </div>\n", "<div style=\"text-align:center\">Figure 2: Learning a teleportation protocol with LOCCNet. </div>\n",
"\n", "\n",
"\n",
"**Note:** In order to make sure the parameters in parameterized quantum circuit is valid for all state after training, we set the training set as 4 linear independent states, which is $\\{|0\\rangle\\langle 0|,|1\\rangle\\langle 1|,|+\\rangle\\langle +|,|+\\rangle\\langle +|_y\\}$ or in the density matrix form:\n", "**Note:** In order to make sure the parameters in parameterized quantum circuit is valid for all state after training, we set the training set as 4 linear independent states, which is $\\{|0\\rangle\\langle 0|,|1\\rangle\\langle 1|,|+\\rangle\\langle +|,|+\\rangle\\langle +|_y\\}$ or in the density matrix form:\n",
"\n", "\n",
"$$\n", "$$\n",
...@@ -359,11 +351,11 @@ ...@@ -359,11 +351,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T08:55:21.137306Z", "end_time": "2021-03-09T06:29:08.878062Z",
"start_time": "2021-01-25T08:55:21.083649Z" "start_time": "2021-03-09T06:29:08.796051Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -371,10 +363,7 @@ ...@@ -371,10 +363,7 @@
"class LOCC_Train(LoccNet):\n", "class LOCC_Train(LoccNet):\n",
" def __init__(self):\n", " def __init__(self):\n",
" super(LOCC_Train, self).__init__()\n", " super(LOCC_Train, self).__init__()\n",
" \n", "\n",
" # Initialize LOCCNet\n",
" self.parties = list()\n",
" \n",
" # Add the first party Alice \n", " # Add the first party Alice \n",
" # The first parameter 2 stands for how many qubits A holds\n", " # The first parameter 2 stands for how many qubits A holds\n",
" # The second parameter records the name of this qubit holder\n", " # The second parameter records the name of this qubit holder\n",
...@@ -387,27 +376,25 @@ ...@@ -387,27 +376,25 @@
" \n", " \n",
"\n", "\n",
" # Create a bell state\n", " # Create a bell state\n",
" _state = fluid.dygraph.to_variable(bell_state(2))\n", " _state = paddle.to_tensor(bell_state(2))\n",
"# _state = fluid.dygraph.to_variable(isotropic_state(2, 0.8))\n", " # _state = paddle.to_tensor(isotropic_state(2, 0.8))\n",
"\n", "\n",
"\n", "\n",
" # Initialize Alice‘s parameters\n", " # Initialize Alice‘s parameters\n",
" self.theta_A = self.create_parameter(shape=[15], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, \n", " self.theta_A = self.create_parameter(shape=[15], default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n",
" seed=SEED), dtype=\"float64\")\n",
" # Initialize Bob's parameters\n", " # Initialize Bob's parameters\n",
" self.theta_B = self.create_parameter(shape=[4, 3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, \n", " self.theta_B = self.create_parameter(shape=[4, 3], default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi), dtype=\"float64\")\n",
" seed=SEED), dtype=\"float64\")\n",
"\n", "\n",
" # Training set: 4 linear independent states\n", " # Training set: 4 linear independent states\n",
" _state0 = fluid.dygraph.to_variable(np.array([[1, 0], [0, 0]], dtype=np.complex128))\n", " _state0 = paddle.to_tensor(np.array([[1, 0], [0, 0]], dtype=np.complex128))\n",
" _state1 = fluid.dygraph.to_variable(np.array([[0, 0], [0, 1]], dtype=np.complex128))\n", " _state1 = paddle.to_tensor(np.array([[0, 0], [0, 1]], dtype=np.complex128))\n",
" _state2 = fluid.dygraph.to_variable(np.array([[0.5, 0.5], [0.5, 0.5]], dtype=np.complex128))\n", " _state2 = paddle.to_tensor(np.array([[0.5, 0.5], [0.5, 0.5]], dtype=np.complex128))\n",
" _state3 = fluid.dygraph.to_variable(np.array([[0.5, -0.5j], [0.5j, 0.5]], dtype=np.complex128))\n", " _state3 = paddle.to_tensor(np.array([[0.5, -0.5j], [0.5j, 0.5]], dtype=np.complex128))\n",
" self.init_states = [_state0, _state1, _state2, _state3]\n", " self.init_states = [_state0, _state1, _state2, _state3]\n",
"\n", "\n",
" # Initialize the system by distributing states between Alice and Bob\n", " # Initialize the system by distributing states between Alice and Bob\n",
" self.set_init_status(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n", " self.set_init_state(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n",
" self.set_init_status(_state0, [(\"Alice\", 0)])\n", " self.set_init_state(_state0, [(\"Alice\", 0)])\n",
"\n", "\n",
" def LOCCNet(self):\n", " def LOCCNet(self):\n",
" \n", " \n",
...@@ -448,62 +435,83 @@ ...@@ -448,62 +435,83 @@
" status_fin = self.partial_state(status_B, [(\"Bob\", 0)])\n", " status_fin = self.partial_state(status_B, [(\"Bob\", 0)])\n",
" \n", " \n",
" # Summing up the loss function for all possible measurement results\n", " # Summing up the loss function for all possible measurement results\n",
" loss += 1 - trace(matmul(init_state, status_fin.state)).real[0]\n", " loss += 1 - paddle.real(trace(matmul(init_state, status_fin.state)))[0]\n",
" \n", " \n",
" return loss\n", " return loss\n",
"\n", "\n",
" # Save the optimized parameters\n", " # Save the optimized parameters\n",
" def save_module(self):\n", " def save_module(self):\n",
" theta = np.array([self.theta_A.numpy(), self.theta_B.numpy()])\n", " theta = np.array([self.theta_A.numpy(), self.theta_B.numpy()], dtype=\"object\")\n",
" np.save('parameters/QT_LOCCNet', theta)" " np.save('parameters/QT_LOCCNet', theta)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T08:57:14.202778Z", "end_time": "2021-03-09T06:30:12.560553Z",
"start_time": "2021-01-25T08:55:21.148860Z" "start_time": "2021-03-09T06:29:11.902232Z"
} }
}, },
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"itr 0: 7.721435597307273\n",
"itr 10: 0.5636061774837096\n",
"itr 20: 0.20642802374795632\n",
"itr 30: 0.07340371172539029\n",
"itr 40: 0.025112969166681598\n",
"itr 50: 0.008655519545057166\n",
"itr 60: 0.0035853096929094885\n",
"itr 70: 0.0014441032202451298\n",
"itr 80: 0.0004540960989092291\n",
"itr 90: 0.00018530025729923683\n",
"itr 100: 4.679932743989479e-05\n",
"itr 110: 1.5186530775368468e-05\n",
"itr 120: 4.8322085606233856e-06\n",
"itr 130: 3.08099659207528e-06\n",
"itr 140: 1.0481638913484304e-06\n"
]
}
],
"source": [ "source": [
"ITR = 150 # Number of iterations\n", "ITR = 150 # Number of iterations\n",
"LR = 0.2 # Set up learning rate\n", "LR = 0.2 # Set up learning rate\n",
"SEED = 999 # Fix random seed for parameters in PQC\n", "SEED = 999 # Fix random seed for parameters in PQC\n",
"np.random.seed(SEED)\n",
"paddle.seed(SEED)\n",
"\n", "\n",
"# Initialize the dynamic graph mode\n", "net = LOCC_Train()\n",
"with fluid.dygraph.guard():\n", "\n",
"\n", "# Choose the Adam optimizer\n",
" net = LOCC_Train()\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters= net.parameters())\n",
" \n", "\n",
" # Choose the Adam optimizer\n", "# Record loss\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list= net.parameters())\n", "loss_list = []\n",
" \n", "\n",
" # Record loss\n", "# Optimization loop\n",
" loss_list = []\n", "for itr in range(ITR):\n",
" \n", "\n",
" # Optimization loop\n", " # Forward propagation to calculate loss function\n",
" for itr in range(ITR):\n", " loss = net.LOCCNet()\n",
" \n", "\n",
" # Forward propagation to calculate loss function\n", " # Backpropagation\n",
" loss = net.LOCCNet()\n", " loss.backward()\n",
" \n", " opt.minimize(loss)\n",
" # Backpropagation\n", "\n",
" loss.backward()\n", " # Clean gradients\n",
" opt.minimize(loss)\n", " opt.clear_grad()\n",
" \n", "\n",
" # Clean gradients\n", " # Record the learning process\n",
" net.clear_gradients()\n", " loss_list.append(loss.numpy()[0])\n",
" \n", " if itr % 10 == 0:\n",
" # Record the learning process\n", " print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n",
" loss_list.append(loss.numpy()[0])\n", "\n",
" if itr % 10 == 0:\n", "# Save parameters\n",
" print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n", "net.save_module()"
" \n",
" # Save parameters\n",
" net.save_module()"
] ]
}, },
{ {
...@@ -517,11 +525,11 @@ ...@@ -517,11 +525,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T08:59:22.381620Z", "end_time": "2021-02-23T09:20:18.582863Z",
"start_time": "2021-01-25T08:59:22.368180Z" "start_time": "2021-02-23T09:20:18.568348Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -534,14 +542,14 @@ ...@@ -534,14 +542,14 @@
" self.add_new_party(2, party_name=\"Alice\")\n", " self.add_new_party(2, party_name=\"Alice\")\n",
" self.add_new_party(1, party_name=\"Bob\")\n", " self.add_new_party(1, party_name=\"Bob\")\n",
" \n", " \n",
" self.theta_A = fluid.dygraph.to_variable(para[0])\n", " self.theta_A = paddle.to_tensor(para[0])\n",
" self.theta_B = fluid.dygraph.to_variable(para[1])\n", " self.theta_B = paddle.to_tensor(para[1])\n",
" \n", " \n",
" _state = fluid.dygraph.to_variable(bell_state(2))\n", " _state = paddle.to_tensor(bell_state(2))\n",
" random_state = density_op_random(n=1)\n", " random_state = density_op_random(n=1)\n",
" self._state0 = fluid.dygraph.to_variable(random_state)\n", " self._state0 = paddle.to_tensor(random_state)\n",
" self.set_init_status(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n", " self.set_init_state(_state, [(\"Alice\", 1), (\"Bob\", 0)])\n",
" self.set_init_status(self._state0, [(\"Alice\", 0)])\n", " self.set_init_state(self._state0, [(\"Alice\", 0)])\n",
" \n", " \n",
"\n", "\n",
" def benchmark(self):\n", " def benchmark(self):\n",
...@@ -567,11 +575,11 @@ ...@@ -567,11 +575,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-25T09:00:01.169427Z", "end_time": "2021-02-23T09:20:33.607232Z",
"start_time": "2021-01-25T08:59:22.909640Z" "start_time": "2021-02-23T09:20:22.038477Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -579,24 +587,24 @@ ...@@ -579,24 +587,24 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"LOCCNet_Fidelity_avg: 1.0 , std= 5.695904177817817e-07\n" "LOCCNet_Fidelity_avg: 1.0 , std= 5.695904182530426e-07\n"
] ]
} }
], ],
"source": [ "source": [
"with fluid.dygraph.guard():\n", "# Load pre-trained circuit parameters\n",
"\n", "para = np.load('parameters/QT_LOCCNet_Trained.npy', allow_pickle=True)\n",
" # Load pre-trained circuit parameters\n", "np.random.seed(999) # Fix random seed\n",
" para = np.load('parameters/QT_LOCCNet_Trained.npy', allow_pickle=True)\n", "num_state = 200 # Number of random states generated\n",
" np.random.seed(999) # Fix random seed\n", "list_fid = [] # Record the fidelity\n",
" num_state = 200 # Number of random states generated\n", "np.random.seed(SEED)\n",
" list_fid = [] # Record the fidelity\n", "paddle.seed(SEED)\n",
" \n", "\n",
" # Start sampling\n", "# Start sampling\n",
" for idx in range(num_state):\n", "for idx in range(num_state):\n",
" list_fid.append(LOCC_Test().benchmark())\n", " list_fid.append(LOCC_Test().benchmark())\n",
"\n", "\n",
" print('LOCCNet_Fidelity_avg:', np.around(sum(list_fid)/len(list_fid), 4), ', std=', np.std(list_fid))" "print('LOCCNet_Fidelity_avg:', np.around(sum(list_fid)/len(list_fid), 4), ', std=', np.std(list_fid))"
] ]
}, },
{ {
...@@ -642,7 +650,7 @@ ...@@ -642,7 +650,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "worse-village",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 利用 LOCC 来进行两方量子态分辨\n", "# 利用 LOCC 来进行两方量子态分辨\n",
...@@ -13,17 +12,15 @@ ...@@ -13,17 +12,15 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "important-allowance",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## 概述\n", "## 概述\n",
"\n", "\n",
"量子态分辨(Quantum State DiscriminationQSD)[1-2] 是量子通信,量子计算和量子密码学中的一个基本问题。本教程展示了如何通过本地量子操作和经典通信(LOCC)来区分满足 $\\langle\\psi\\lvert\\phi\\rangle=0$ 的两个正交的两方纯态 $\\lvert\\psi\\rangle$ 和 $\\lvert\\phi\\rangle$。本教程中使用的方法和理论参考了 [3] 。\n" "量子态分辨(Quantum State Discrimination, QSD)[1-2] 是量子通信,量子计算和量子密码学中的一个基本问题。本教程展示了如何通过本地量子操作和经典通信(LOCC)来区分满足 $\\langle\\psi\\lvert\\phi\\rangle=0$ 的两个正交的两方纯态 $\\lvert\\psi\\rangle$ 和 $\\lvert\\phi\\rangle$。本教程中使用的方法和理论参考了 [3] 。\n"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "accomplished-horror",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## 寻找一个态分辨协议\n", "## 寻找一个态分辨协议\n",
...@@ -39,7 +36,7 @@ ...@@ -39,7 +36,7 @@
"\n", "\n",
"其中 $p_{\\lvert\\psi\\rangle\\_01}$ 代表输入态为 $\\lvert\\psi\\rangle$ 时测量 01 的概率(**注释:** 这是一种分类错误的情况)。接着我们可以通过优化算法来最小化损失函数。\n", "其中 $p_{\\lvert\\psi\\rangle\\_01}$ 代表输入态为 $\\lvert\\psi\\rangle$ 时测量 01 的概率(**注释:** 这是一种分类错误的情况)。接着我们可以通过优化算法来最小化损失函数。\n",
"\n", "\n",
"<center><img src=\"figures/discrimination-fig-circuit.png\" height=\"300\" width=\"450\"></center>\n", "![](figures/discrimination-fig-circuit.png \"图 1. 用 LOCCNet 进行两方态分辨的协议示意图\")\n",
"<div style=\"text-align:center\">图 1. 用 LOCCNet 进行两方态分辨的协议示意图 </div>\n", "<div style=\"text-align:center\">图 1. 用 LOCCNet 进行两方态分辨的协议示意图 </div>\n",
"\n", "\n",
"我们将整个流程进行如下总结:\n", "我们将整个流程进行如下总结:\n",
...@@ -57,7 +54,6 @@ ...@@ -57,7 +54,6 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "stuffed-soccer",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Paddle Quantum 代码实现\n", "## Paddle Quantum 代码实现\n",
...@@ -68,24 +64,22 @@ ...@@ -68,24 +64,22 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 1,
"id": "crazy-mention",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T09:46:01.773791Z", "end_time": "2021-03-09T04:10:28.022626Z",
"start_time": "2021-01-27T09:45:56.319880Z" "start_time": "2021-03-09T04:10:23.716087Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"from scipy.stats import unitary_group\n", "from scipy.stats import unitary_group\n",
"import paddle.fluid as fluid\n", "import paddle\n",
"from paddle_quantum.locc import LoccNet" "from paddle_quantum.locc import LoccNet"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "abandoned-divide",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Charlie 需要随机生成两个正交态 $\\lvert\\psi\\rangle$ 以及 $\\lvert\\phi\\rangle$。" "Charlie 需要随机生成两个正交态 $\\lvert\\psi\\rangle$ 以及 $\\lvert\\phi\\rangle$。"
...@@ -94,11 +88,10 @@ ...@@ -94,11 +88,10 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 2,
"id": "seasonal-enemy",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T09:46:01.811464Z", "end_time": "2021-03-09T04:10:38.723834Z",
"start_time": "2021-01-27T09:46:01.801909Z" "start_time": "2021-03-09T04:10:38.718397Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -116,7 +109,6 @@ ...@@ -116,7 +109,6 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "necessary-think",
"metadata": {}, "metadata": {},
"source": [ "source": [
"下面是我们代码的主要部分,它定义了 Alice 和 Bob 的本地量子操作和损失函数。" "下面是我们代码的主要部分,它定义了 Alice 和 Bob 的本地量子操作和损失函数。"
...@@ -125,16 +117,15 @@ ...@@ -125,16 +117,15 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 3,
"id": "attempted-therapy",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T09:46:02.017296Z", "end_time": "2021-03-09T04:10:39.769534Z",
"start_time": "2021-01-27T09:46:01.990328Z" "start_time": "2021-03-09T04:10:39.714589Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Net (LoccNet):\n", "class Net(LoccNet):\n",
" def __init__(self):\n", " def __init__(self):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
" \n", " \n",
...@@ -149,21 +140,24 @@ ...@@ -149,21 +140,24 @@
" self.add_new_party(1, party_name='Bob')\n", " self.add_new_party(1, party_name='Bob')\n",
" \n", " \n",
" # 初始化 Alice 的参数\n", " # 初始化 Alice 的参数\n",
" self.theta1 = self.create_parameter(shape=[3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, seed=SEED),\n", " self.theta1 = self.create_parameter(shape=[3],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),\n",
" dtype=\"float64\")\n", " dtype=\"float64\")\n",
" # 初始化 Bob 的参数\n", " # 初始化 Bob 的参数\n",
" # Bob 要准备两个电路来应对两个不同的测量结果\n", " # Bob 要准备两个电路来应对两个不同的测量结果\n",
" self.theta2 = self.create_parameter(shape=[3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, seed=SEED),\n", " self.theta2 = self.create_parameter(shape=[3],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),\n",
" dtype=\"float64\")\n", " dtype=\"float64\")\n",
" self.theta3 = self.create_parameter(shape=[3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, seed=SEED),\n", " self.theta3 = self.create_parameter(shape=[3],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),\n",
" dtype=\"float64\")\n", " dtype=\"float64\")\n",
" \n", " \n",
" # 将输入态写成密度矩阵形式\n", " # 将输入态写成密度矩阵形式\n",
" _states = states_orthogonal_random(2)\n", " _states = states_orthogonal_random(2)\n",
" _states = [fluid.dygraph.to_variable(np.outer(init_state, init_state.conjugate())) for init_state in _states]\n", " _states = [paddle.to_tensor(np.outer(init_state, init_state.conjugate())) for init_state in _states]\n",
" \n", " \n",
" # 初始化整个量子系统并分配量子态\n", " # 初始化整个量子系统并分配量子态\n",
" self.set_init_status(_states[0], [('Alice', 0), ('Bob', 0)])\n", " self.set_init_state(_states[0], [('Alice', 0), ('Bob', 0)])\n",
" self.psi = self.init_status\n", " self.psi = self.init_status\n",
" self.phi = self.reset_state(self.init_status, _states[1], [('Alice', 0), ('Bob', 0)])\n", " self.phi = self.reset_state(self.init_status, _states[1], [('Alice', 0), ('Bob', 0)])\n",
"\n", "\n",
...@@ -247,7 +241,6 @@ ...@@ -247,7 +241,6 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "dense-kidney",
"metadata": {}, "metadata": {},
"source": [ "source": [
"训练 Alice 和 Bob 的电路,然后随机选择两个正交态 $\\lvert\\psi\\rangle$ 和 $\\lvert\\phi\\rangle$ 之一以通过我们训练的电路,以检查它们是否可以区分。" "训练 Alice 和 Bob 的电路,然后随机选择两个正交态 $\\lvert\\psi\\rangle$ 和 $\\lvert\\phi\\rangle$ 之一以通过我们训练的电路,以检查它们是否可以区分。"
...@@ -256,11 +249,10 @@ ...@@ -256,11 +249,10 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 4,
"id": "theoretical-sampling",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T09:46:12.711030Z", "end_time": "2021-03-09T04:10:45.887729Z",
"start_time": "2021-01-27T09:46:02.987658Z" "start_time": "2021-03-09T04:10:40.821447Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -268,24 +260,24 @@ ...@@ -268,24 +260,24 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"itr 0: 0.41451205406019975\n", "itr 0: 0.8761168230331675\n",
"itr 10: 0.028321852355670925\n", "itr 10: 0.20833627335270305\n",
"itr 20: 0.03680755589712137\n", "itr 20: 0.09979993875586758\n",
"itr 30: 0.020398244027029454\n", "itr 30: 0.05990778041973435\n",
"itr 40: 0.008193744818255858\n", "itr 40: 0.02806489116318598\n",
"itr 50: 0.004566371117377564\n", "itr 50: 0.026191291836946892\n",
"itr 60: 0.0024181967231273298\n", "itr 60: 0.02245618597383097\n",
"itr 70: 0.0010470019789715651\n", "itr 70: 0.01903560177140634\n",
"itr 80: 0.00040675868734474884\n", "itr 80: 0.016262801555360196\n",
"itr 90: 0.00012631312259401648\n", "itr 90: 0.011920717566034985\n",
"最小损失: 3.333578751225666e-05\n", "最小损失: 0.0077142257760679424\n",
"======================== 测试阶段 ===============================\n", "======================== 测试阶段 ===============================\n",
"Charlie 选择的态是 psi\n", "Charlie 选择的态是 psi\n",
"Alice 和 Bob 将这个态分辨为 phi 的概率为: 2.1562924160659577e-05\n", "Alice 和 Bob 将这个态分辨为 phi 的概率为: 0.003188464207077198\n",
"Alice 和 Bob 将这个态分辨为 psi 的概率为: 0.9999784370758389\n", "Alice 和 Bob 将这个态分辨为 psi 的概率为: 0.9968115357929229\n",
"Charlie 选择的态是 phi\n", "Charlie 选择的态是 phi\n",
"Alice 和 Bob 将这个态分辨为 phi 的概率为: 0.9999920892819899\n", "Alice 和 Bob 将这个态分辨为 phi 的概率为: 0.99590992116251\n",
"Alice 和 Bob 将这个态分辨为 psi 的概率为: 7.910718009026491e-06\n" "Alice 和 Bob 将这个态分辨为 psi 的概率为: 0.004090078837489469\n"
] ]
} }
], ],
...@@ -293,35 +285,32 @@ ...@@ -293,35 +285,32 @@
"ITR = 100 # 设置训练步数\n", "ITR = 100 # 设置训练步数\n",
"LR = 0.1 # 设置学习速率\n", "LR = 0.1 # 设置学习速率\n",
"SEED = 999 # 固定 PQC 中参数的随机种子\n", "SEED = 999 # 固定 PQC 中参数的随机种子\n",
"np.random.seed(999)\n", "np.random.seed(SEED)\n",
"paddle.seed(SEED)\n",
"\n", "\n",
"net = Net()\n",
"opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"loss_list = list()\n",
"# 通过梯度下降训练 LOCC 网络以进行 ITR 次迭代\n",
"for itr in range(ITR):\n",
" loss = net()\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" opt.clear_grad()\n",
" loss_list.append(loss.numpy()[0])\n",
" if itr % 10 == 0:\n",
" print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n",
"print(\"最小损失:\", loss_list[-1])\n",
"\n", "\n",
"# 初始化动态图模式\n", "print(\"======================== 测试阶段 ===============================\")\n",
"with fluid.dygraph.guard():\n", "np.random.seed(10)\n",
" net = Net()\n", "net.evaluate()\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "np.random.seed(6)\n",
" loss_list = list()\n", "net.evaluate()"
" # 通过梯度下降训练 LOCC 网络以进行 ITR 次迭代\n",
" for itr in range(ITR):\n",
" loss = net()\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" net.clear_gradients()\n",
" loss_list.append(loss.numpy()[0])\n",
" if itr % 10 == 0:\n",
" print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n",
" print(\"最小损失:\", loss_list[-1])\n",
" \n",
" print(\"======================== 测试阶段 ===============================\")\n",
" np.random.seed(10)\n",
" net.evaluate()\n",
" np.random.seed(6)\n",
" net.evaluate()"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "ordered-concern",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## 结论\n", "## 结论\n",
...@@ -331,7 +320,6 @@ ...@@ -331,7 +320,6 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "nasty-money",
"metadata": {}, "metadata": {},
"source": [ "source": [
"---\n", "---\n",
...@@ -361,7 +349,7 @@ ...@@ -361,7 +349,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.12" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
"source": [ "source": [
"## Overview\n", "## Overview\n",
"\n", "\n",
"Quantum state discrimination (QSD) [1-2] is a fundamental question in quantum communication, quantum computation, and quantum cryptography. In this tutorial, we will explain how to discriminate two orthogonal bipartite pure states $\\lvert\\psi\\rangle$ and $\\lvert\\phi\\rangle$, which satisfies $\\langle\\psi\\lvert\\phi\\rangle=0$, under the constraint of Local Operations and Classical Communication (LOCC). We refer all the theoretical details to the original paper [3].\n" "Quantum state discrimination (QSD) [1-2] is a fundamental question in quantum communication, quantum computation, and quantum cryptography. In this tutorial, we will explain how to discriminate two orthogonal bipartite pure states $\\lvert\\psi\\rangle$ and $\\lvert\\phi\\rangle$, which satisfies $\\langle\\psi\\lvert\\phi\\rangle=0$, under the constraint of Local Operations and Classical Communication (LOCC). We refer all the theoretical details to the original paper [3]."
] ]
}, },
{ {
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
"source": [ "source": [
"## QSD Protocol\n", "## QSD Protocol\n",
"\n", "\n",
"\n",
"Firstly, we want to make the problem definition clear. Consider two spatially separated parties $A$ (Alice) and $B$ (Bob) share a given two-qubit system, the system state is $\\lvert\\varphi\\rangle$ previously distributed by another party $C$ (Charlie). Alice and Bob were only notified that $\\lvert\\varphi\\rangle$ is either $\\lvert\\psi\\rangle$ or $\\lvert\\phi\\rangle$ (both are pure states), satisfying $\\langle\\psi\\lvert\\phi\\rangle=0$. Then, Charlie provides many copies of $\\lvert\\psi\\rangle$ and $\\lvert\\phi\\rangle$ to them, and he asks Alice and Bob to cooperate with each other to figure out which state they are actually sharing.\n", "Firstly, we want to make the problem definition clear. Consider two spatially separated parties $A$ (Alice) and $B$ (Bob) share a given two-qubit system, the system state is $\\lvert\\varphi\\rangle$ previously distributed by another party $C$ (Charlie). Alice and Bob were only notified that $\\lvert\\varphi\\rangle$ is either $\\lvert\\psi\\rangle$ or $\\lvert\\phi\\rangle$ (both are pure states), satisfying $\\langle\\psi\\lvert\\phi\\rangle=0$. Then, Charlie provides many copies of $\\lvert\\psi\\rangle$ and $\\lvert\\phi\\rangle$ to them, and he asks Alice and Bob to cooperate with each other to figure out which state they are actually sharing.\n",
"\n", "\n",
"\n", "\n",
...@@ -39,7 +38,7 @@ ...@@ -39,7 +38,7 @@
"where $p_{\\lvert\\psi\\rangle\\_01}$ stands for the probability of measuring 01 when the input state is $\\lvert\\psi\\rangle$. Then we can begin the training stage to minimize the loss function.\n", "where $p_{\\lvert\\psi\\rangle\\_01}$ stands for the probability of measuring 01 when the input state is $\\lvert\\psi\\rangle$. Then we can begin the training stage to minimize the loss function.\n",
"\n", "\n",
"\n", "\n",
"<center><img src=\"figures/discrimination-fig-circuit.png\" height=\"300\" width=\"450\"></center>\n", "![qsd](figures/discrimination-fig-circuit.png \"Figure 1: Schematic diagram of state discrimination with LOCCNet.\")\n",
"<div style=\"text-align:center\">Figure 1: Schematic diagram of state discrimination with LOCCNet. </div>\n", "<div style=\"text-align:center\">Figure 1: Schematic diagram of state discrimination with LOCCNet. </div>\n",
"\n", "\n",
"\n", "\n",
...@@ -52,9 +51,7 @@ ...@@ -52,9 +51,7 @@
"4. Bob operates different gates on his qubit depending on Alice's measurement result. If, $m_A=0$ Bob acts $U_{B0}$ on his qubit; If $m_A = 1$, then Bob acts $U_{B1}$. Then, Bob measures his qubit and obtain $m_B \\in \\{0,1\\}$. **Note**: Both $U_{B0}$ and $U_{B1}$ are universal single-qubit gate `u3()`.\n", "4. Bob operates different gates on his qubit depending on Alice's measurement result. If, $m_A=0$ Bob acts $U_{B0}$ on his qubit; If $m_A = 1$, then Bob acts $U_{B1}$. Then, Bob measures his qubit and obtain $m_B \\in \\{0,1\\}$. **Note**: Both $U_{B0}$ and $U_{B1}$ are universal single-qubit gate `u3()`.\n",
"5. Calculate the loss function $L = p_{\\lvert\\psi\\rangle\\_01}+p_{\\lvert\\psi\\rangle\\_11}+ p_{\\lvert\\phi\\rangle\\_10}+ p_{\\lvert\\phi\\rangle\\_00}$, and use gradient-based optimization methods to minimize it.\n", "5. Calculate the loss function $L = p_{\\lvert\\psi\\rangle\\_01}+p_{\\lvert\\psi\\rangle\\_11}+ p_{\\lvert\\phi\\rangle\\_10}+ p_{\\lvert\\phi\\rangle\\_00}$, and use gradient-based optimization methods to minimize it.\n",
"6. Repeat 1-5 until the loss function converges.\n", "6. Repeat 1-5 until the loss function converges.\n",
"7. Input the pre-shared state $\\lvert\\varphi\\rangle$ to make a decision and compare with Charlie's answer.\n", "7. Input the pre-shared state $\\lvert\\varphi\\rangle$ to make a decision and compare with Charlie's answer."
"\n",
"\n"
] ]
}, },
{ {
...@@ -71,15 +68,15 @@ ...@@ -71,15 +68,15 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T09:44:41.820485Z", "end_time": "2021-03-09T04:11:04.474304Z",
"start_time": "2021-01-27T09:44:35.116796Z" "start_time": "2021-03-09T04:11:01.071347Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"from scipy.stats import unitary_group\n", "from scipy.stats import unitary_group\n",
"import paddle.fluid as fluid\n", "import paddle\n",
"from paddle_quantum.locc import LoccNet" "from paddle_quantum.locc import LoccNet"
] ]
}, },
...@@ -95,8 +92,8 @@ ...@@ -95,8 +92,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T09:44:41.851407Z", "end_time": "2021-03-09T04:11:04.498238Z",
"start_time": "2021-01-27T09:44:41.823614Z" "start_time": "2021-03-09T04:11:04.478356Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -124,13 +121,13 @@ ...@@ -124,13 +121,13 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T09:44:41.961552Z", "end_time": "2021-03-09T04:11:04.551149Z",
"start_time": "2021-01-27T09:44:41.880659Z" "start_time": "2021-03-09T04:11:04.506818Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Net (LoccNet):\n", "class Net(LoccNet):\n",
" def __init__(self):\n", " def __init__(self):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
" \n", " \n",
...@@ -145,21 +142,24 @@ ...@@ -145,21 +142,24 @@
" self.add_new_party(1, party_name='Bob')\n", " self.add_new_party(1, party_name='Bob')\n",
" \n", " \n",
" # Initialize Alice's parameter\n", " # Initialize Alice's parameter\n",
" self.theta1 = self.create_parameter(shape=[3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, seed=SEED),\n", " self.theta1 = self.create_parameter(shape=[3],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),\n",
" dtype=\"float64\")\n", " dtype=\"float64\")\n",
" # Initialize Bob's parameter\n", " # Initialize Bob's parameter\n",
" # Bob has to prepare two circuits according Alice's measurement result \n", " # Bob has to prepare two circuits according Alice's measurement result \n",
" self.theta2 = self.create_parameter(shape=[3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, seed=SEED),\n", " self.theta2 = self.create_parameter(shape=[3],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),\n",
" dtype=\"float64\")\n", " dtype=\"float64\")\n",
" self.theta3 = self.create_parameter(shape=[3], attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, seed=SEED),\n", " self.theta3 = self.create_parameter(shape=[3],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),\n",
" dtype=\"float64\")\n", " dtype=\"float64\")\n",
" \n", " \n",
" # Rewrite the input states into density martices\n", " # Rewrite the input states into density martices\n",
" _states = states_orthogonal_random(2)\n", " _states = states_orthogonal_random(2)\n",
" _states = [fluid.dygraph.to_variable(np.outer(init_state, init_state.conjugate())) for init_state in _states]\n", " _states = [paddle.to_tensor(np.outer(init_state, init_state.conjugate())) for init_state in _states]\n",
" \n", " \n",
" # Initialize the system by distributing states\n", " # Initialize the system by distributing states\n",
" self.set_init_status(_states[0], [('Alice', 0), ('Bob', 0)])\n", " self.set_init_state(_states[0], [('Alice', 0), ('Bob', 0)])\n",
" self.psi = self.init_status\n", " self.psi = self.init_status\n",
" self.phi = self.reset_state(self.init_status, _states[1], [('Alice', 0), ('Bob', 0)])\n", " self.phi = self.reset_state(self.init_status, _states[1], [('Alice', 0), ('Bob', 0)])\n",
"\n", "\n",
...@@ -253,8 +253,8 @@ ...@@ -253,8 +253,8 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-27T09:44:54.808382Z", "end_time": "2021-03-09T04:11:19.312821Z",
"start_time": "2021-01-27T09:44:41.997674Z" "start_time": "2021-03-09T04:11:14.759835Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -262,24 +262,24 @@ ...@@ -262,24 +262,24 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"itr 0: 0.41451205406020003\n", "itr 0: 0.8761168230331675\n",
"itr 10: 0.028321852355736393\n", "itr 10: 0.20833627335270305\n",
"itr 20: 0.03680755589726499\n", "itr 20: 0.09979993875586758\n",
"itr 30: 0.020398244027092\n", "itr 30: 0.05990778041973435\n",
"itr 40: 0.00819374481825746\n", "itr 40: 0.02806489116318598\n",
"itr 50: 0.00456637111735521\n", "itr 50: 0.026191291836946892\n",
"itr 60: 0.00241819672311186\n", "itr 60: 0.02245618597383097\n",
"itr 70: 0.0010470019789628306\n", "itr 70: 0.01903560177140634\n",
"itr 80: 0.0004067586873393533\n", "itr 80: 0.016262801555360196\n",
"itr 90: 0.0001263131225914237\n", "itr 90: 0.011920717566034985\n",
"Minimum loss: 3.33357875113083e-05\n", "Minimum loss: 0.0077142257760679424\n",
"======================== test stage ===============================\n", "======================== test stage ===============================\n",
"Charlie chooses the state psi\n", "Charlie chooses the state psi\n",
"The probability that Alice and Bob recognize it as phi: 2.1562924160375818e-05\n", "The probability that Alice and Bob recognize it as phi: 0.003188464207077198\n",
"The probability that Alice and Bob recognize it as psi: 0.9999784370758396\n", "The probability that Alice and Bob recognize it as psi: 0.9968115357929229\n",
"Charlie chooses the state phi\n", "Charlie chooses the state phi\n",
"The probability that Alice and Bob recognize it as phi: 0.9999920892819907\n", "The probability that Alice and Bob recognize it as phi: 0.99590992116251\n",
"The probability that Alice and Bob recognize it as psi: 7.91071800851656e-06\n" "The probability that Alice and Bob recognize it as psi: 0.004090078837489469\n"
] ]
} }
], ],
...@@ -287,30 +287,28 @@ ...@@ -287,30 +287,28 @@
"ITR = 100 # Set the number of training iterations\n", "ITR = 100 # Set the number of training iterations\n",
"LR = 0.1 # Set learning rate\n", "LR = 0.1 # Set learning rate\n",
"SEED = 999 # Fix randome seed for parameters in PQC\n", "SEED = 999 # Fix randome seed for parameters in PQC\n",
"np.random.seed(999)\n", "np.random.seed(SEED)\n",
"paddle.seed(SEED)\n",
"\n", "\n",
"net = Net()\n",
"opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"loss_list = list()\n",
"# Train the LOCC net for ITR iterations by gradient descent\n",
"for itr in range(ITR):\n",
" loss = net()\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" opt.clear_grad()\n",
" loss_list.append(loss.numpy()[0])\n",
" if itr % 10 == 0:\n",
" print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n",
"print(\"Minimum loss:\", loss_list[-1])\n",
"\n", "\n",
"# Initialize dynamic graph mode\n", "print(\"======================== test stage ===============================\")\n",
"with fluid.dygraph.guard():\n", "np.random.seed(10)\n",
" net = Net()\n", "net.evaluate()\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "np.random.seed(6)\n",
" loss_list = list()\n", "net.evaluate()"
" # Train the LOCC net for ITR iterations by gradient descent\n",
" for itr in range(ITR):\n",
" loss = net()\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" net.clear_gradients()\n",
" loss_list.append(loss.numpy()[0])\n",
" if itr % 10 == 0:\n",
" print(\"itr \" + str(itr) + \":\", loss.numpy()[0])\n",
" print(\"Minimum loss:\", loss_list[-1])\n",
" \n",
" print(\"======================== test stage ===============================\")\n",
" np.random.seed(10)\n",
" net.evaluate()\n",
" np.random.seed(6)\n",
" net.evaluate()"
] ]
}, },
{ {
...@@ -353,7 +351,7 @@ ...@@ -353,7 +351,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -58,10 +58,10 @@ ...@@ -58,10 +58,10 @@
"import numpy as np\n", "import numpy as np\n",
"from numpy import diag\n", "from numpy import diag\n",
"import scipy\n", "import scipy\n",
"import scipy.stats\n",
"import paddle\n", "import paddle\n",
"from paddle import fluid\n", "from paddle import matmul, trace, kron, real\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle.complex import matmul, trace, kron\n",
"from paddle_quantum.utils import dagger, state_fidelity, partial_trace" "from paddle_quantum.utils import dagger, state_fidelity, partial_trace"
] ]
}, },
...@@ -176,16 +176,16 @@ ...@@ -176,16 +176,16 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 10 loss: 0.1716 fid: 0.8214\n", "iter: 10 loss: 0.1683 fid: 0.8211\n",
"iter: 20 loss: 0.1381 fid: 0.8550\n", "iter: 20 loss: 0.1231 fid: 0.8720\n",
"iter: 30 loss: 0.1124 fid: 0.8813\n", "iter: 30 loss: 0.1122 fid: 0.8810\n",
"iter: 40 loss: 0.1037 fid: 0.8901\n", "iter: 40 loss: 0.1058 fid: 0.8864\n",
"iter: 50 loss: 0.1019 fid: 0.8927\n", "iter: 50 loss: 0.1025 fid: 0.8901\n",
"iter: 60 loss: 0.1007 fid: 0.8935\n", "iter: 60 loss: 0.1019 fid: 0.8907\n",
"iter: 70 loss: 0.1003 fid: 0.8938\n", "iter: 70 loss: 0.1013 fid: 0.8914\n",
"iter: 80 loss: 0.1001 fid: 0.8942\n", "iter: 80 loss: 0.1012 fid: 0.8917\n",
"iter: 90 loss: 0.1000 fid: 0.8943\n", "iter: 90 loss: 0.1010 fid: 0.8921\n",
"iter: 100 loss: 0.1000 fid: 0.8942\n" "iter: 100 loss: 0.1008 fid: 0.8924\n"
] ]
} }
], ],
...@@ -196,17 +196,19 @@ ...@@ -196,17 +196,19 @@
"N = N_A + N_B # 总的量子比特数\n", "N = N_A + N_B # 总的量子比特数\n",
"LR = 0.2 # 设置学习速率\n", "LR = 0.2 # 设置学习速率\n",
"ITR = 100 # 设置迭代次数\n", "ITR = 100 # 设置迭代次数\n",
"SEED = 14 # 固定初始化参数用的随机数种子\n", "SEED = 15 # 固定初始化参数用的随机数种子\n",
"\n", "\n",
"class NET(fluid.dygraph.Layer):\n", "class NET(paddle.nn.Layer):\n",
"\n", "\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * np.pi, seed = SEED), dtype='float64'):\n", " def __init__(self, shape, dtype='float64'):\n",
" super(NET, self).__init__()\n", " super(NET, self).__init__()\n",
" \n", " \n",
" # 将 Numpy array 转换成 Paddle 动态图模式中支持的 variable\n", " # 将 Numpy array 转换成 Paddle 中支持的 Tensor\n",
" self.rho_in = fluid.dygraph.to_variable(rho_in)\n", " self.rho_in = paddle.to_tensor(rho_in)\n",
" self.rho_C = fluid.dygraph.to_variable(rho_C)\n", " self.rho_C = paddle.to_tensor(rho_C)\n",
" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.theta = self.create_parameter(shape=shape,\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # 定义损失函数和前向传播机制\n", " # 定义损失函数和前向传播机制\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -229,38 +231,31 @@ ...@@ -229,38 +231,31 @@
" rho_out = matmul(matmul(D, rho_CA), D_dagger)\n", " rho_out = matmul(matmul(D, rho_CA), D_dagger)\n",
" \n", " \n",
" # 通过 rho_trash 计算损失函数\n", " # 通过 rho_trash 计算损失函数\n",
" zero_Hamiltonian = fluid.dygraph.to_variable(np.diag([1,0]).astype('complex128'))\n", " zero_Hamiltonian = paddle.to_tensor(np.diag([1,0]).astype('complex128'))\n",
" loss = 1 - (trace(matmul(zero_Hamiltonian, rho_trash))).real\n", " loss = 1 - real(trace(matmul(zero_Hamiltonian, rho_trash)))\n",
"\n", "\n",
" return loss, self.rho_in, rho_out\n", " return loss, self.rho_in, rho_out\n",
"\n", "\n",
"\n", "\n",
"# 初始化paddle动态图机制 \n", "paddle.seed(SEED)\n",
"with fluid.dygraph.guard():\n", "# 生成网络\n",
"\n", "net = NET([theta_size])\n",
" # 生成网络\n", "# 一般来说,我们利用 Adam 优化器来获得相对好的收敛\n",
" net = NET([theta_size])\n", "# 当然你可以改成 SGD 或者是 RMS prop.\n",
"\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" # 一般来说,我们利用Adam优化器来获得相对好的收敛\n", "\n",
" # 当然你可以改成SGD或者是RMS prop.\n", "# 优化循环\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "for itr in range(1, ITR + 1):\n",
"\n", " # 前向传播计算损失函数\n",
" # 优化循环\n", " loss, rho_in, rho_out = net()\n",
" for itr in range(1, ITR + 1):\n", " # 反向传播极小化损失函数\n",
" \n", " loss.backward()\n",
" # 前向传播计算损失函数\n", " opt.minimize(loss)\n",
" loss, rho_in, rho_out = net()\n", " opt.clear_grad()\n",
" \n", " # 计算并打印保真度\n",
" # 在动态图机制下,反向传播极小化损失函数\n", " fid = state_fidelity(rho_in.numpy(), rho_out.numpy())\n",
" loss.backward()\n", " if itr % 10 == 0:\n",
" opt.minimize(loss)\n", " print('iter:', itr, 'loss:', '%.4f' % loss, 'fid:', '%.4f' % np.square(fid))"
" net.clear_gradients()\n",
" \n",
" # 计算并打印保真度\n",
" fid = state_fidelity(rho_in.numpy(), rho_out.numpy())\n",
"\n",
" if itr % 10 == 0:\n",
" print('iter:', itr, 'loss:', '%.4f' % loss, 'fid:', '%.4f' % np.square(fid))"
] ]
}, },
{ {
...@@ -307,7 +302,7 @@ ...@@ -307,7 +302,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.10" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -58,10 +58,10 @@ ...@@ -58,10 +58,10 @@
"import numpy as np\n", "import numpy as np\n",
"from numpy import diag\n", "from numpy import diag\n",
"import scipy\n", "import scipy\n",
"import scipy.stats\n",
"import paddle\n", "import paddle\n",
"from paddle import fluid\n", "from paddle import matmul, trace, kron, real\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle.complex import matmul, trace, kron\n",
"from paddle_quantum.utils import dagger, state_fidelity, partial_trace" "from paddle_quantum.utils import dagger, state_fidelity, partial_trace"
] ]
}, },
...@@ -176,16 +176,16 @@ ...@@ -176,16 +176,16 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 10 loss: 0.1716 fid: 0.8214\n", "iter: 10 loss: 0.1683 fid: 0.8211\n",
"iter: 20 loss: 0.1381 fid: 0.8550\n", "iter: 20 loss: 0.1231 fid: 0.8720\n",
"iter: 30 loss: 0.1124 fid: 0.8813\n", "iter: 30 loss: 0.1122 fid: 0.8810\n",
"iter: 40 loss: 0.1037 fid: 0.8901\n", "iter: 40 loss: 0.1058 fid: 0.8864\n",
"iter: 50 loss: 0.1019 fid: 0.8927\n", "iter: 50 loss: 0.1025 fid: 0.8901\n",
"iter: 60 loss: 0.1007 fid: 0.8935\n", "iter: 60 loss: 0.1019 fid: 0.8907\n",
"iter: 70 loss: 0.1003 fid: 0.8938\n", "iter: 70 loss: 0.1013 fid: 0.8914\n",
"iter: 80 loss: 0.1001 fid: 0.8942\n", "iter: 80 loss: 0.1012 fid: 0.8917\n",
"iter: 90 loss: 0.1000 fid: 0.8943\n", "iter: 90 loss: 0.1010 fid: 0.8921\n",
"iter: 100 loss: 0.1000 fid: 0.8942\n" "iter: 100 loss: 0.1008 fid: 0.8924\n"
] ]
} }
], ],
...@@ -196,17 +196,18 @@ ...@@ -196,17 +196,18 @@
"N = N_A + N_B # Total number of qubits\n", "N = N_A + N_B # Total number of qubits\n",
"LR = 0.2 # Set the learning rate\n", "LR = 0.2 # Set the learning rate\n",
"ITR = 100 # Set the number of iterations\n", "ITR = 100 # Set the number of iterations\n",
"SEED = 14 # Fixed random number seed for initializing parameters\n", "SEED = 15 # Fixed random number seed for initializing parameters\n",
"\n", "\n",
"class NET(fluid.dygraph.Layer):\n", "class NET(paddle.nn.Layer):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " def __init__(self, shape, dtype='float64'):\n",
" low=0.0, high=2 * np.pi, seed = SEED), dtype='float64'):\n",
" super(NET, self).__init__()\n", " super(NET, self).__init__()\n",
" \n", " \n",
" # Convert Numpy array to variable supported in PaddlePaddle's dynamic graph mode\n", " # Convert Numpy array to Tensor supported in PaddlePaddle\n",
" self.rho_in = fluid.dygraph.to_variable(rho_in)\n", " self.rho_in = paddle.to_tensor(rho_in)\n",
" self.rho_C = fluid.dygraph.to_variable(rho_C)\n", " self.rho_C = paddle.to_tensor(rho_C)\n",
" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.theta = self.create_parameter(shape=shape,\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -229,38 +230,31 @@ ...@@ -229,38 +230,31 @@
" rho_out = matmul(matmul(D, rho_CA), D_dagger)\n", " rho_out = matmul(matmul(D, rho_CA), D_dagger)\n",
" \n", " \n",
" # Calculate the loss function with rho_trash\n", " # Calculate the loss function with rho_trash\n",
" zero_Hamiltonian = fluid.dygraph.to_variable(np.diag([1,0]).astype('complex128'))\n", " zero_Hamiltonian = paddle.to_tensor(np.diag([1,0]).astype('complex128'))\n",
" loss = 1-(trace(matmul(zero_Hamiltonian, rho_trash))).real\n", " loss = 1 - real(trace(matmul(zero_Hamiltonian, rho_trash)))\n",
"\n", "\n",
" return loss, self.rho_in, rho_out\n", " return loss, self.rho_in, rho_out\n",
"\n", "\n",
"\n", "\n",
"# Initialize PaddlePaddle's dynamic graph mechanism\n", "paddle.seed(SEED)\n",
"with fluid.dygraph.guard():\n", "# Generate network\n",
"\n", "net = NET([theta_size])\n",
" # Generate network\n", "# Generally speaking, we use Adam optimizer to get relatively good convergence\n",
" net = NET([theta_size])\n", "# Of course, it can be changed to SGD or RMS prop.\n",
"\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" # Generally speaking, we use Adam optimizer to get relatively good convergence\n", "\n",
" # Of course, it can be changed to SGD or RMS prop.\n", "# Optimization loops\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "for itr in range(1, ITR + 1):\n",
"\n", " # Forward propagation for calculating loss function\n",
" # Optimization loops\n", " loss, rho_in, rho_out = net()\n",
" for itr in range(1, ITR + 1):\n", " # Use back propagation to minimize the loss function\n",
" \n", " loss.backward()\n",
" # Forward propagation for calculating loss function\n", " opt.minimize(loss)\n",
" loss, rho_in, rho_out = net()\n", " opt.clear_grad()\n",
" \n", " # Calculate and print fidelity\n",
" # Under the dynamic graph mechanism, use back propagation to minimize the loss function\n", " fid = state_fidelity(rho_in.numpy(), rho_out.numpy())\n",
" loss.backward()\n", " if itr% 10 == 0:\n",
" opt.minimize(loss)\n", " print('iter:', itr,'loss:','%.4f'% loss,'fid:','%.4f'% np.square(fid))"
" net.clear_gradients()\n",
" \n",
" # Calculate and print fidelity\n",
" fid = state_fidelity(rho_in.numpy(), rho_out.numpy())\n",
"\n",
" if itr% 10 == 0:\n",
" print('iter:', itr,'loss:','%.4f'% loss,'fid:','%.4f'% np.square(fid))"
] ]
}, },
{ {
...@@ -306,7 +300,7 @@ ...@@ -306,7 +300,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.10" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -219,11 +219,9 @@ ...@@ -219,11 +219,9 @@
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle\n", "import paddle\n",
"from paddle import fluid\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import partial_trace, dagger, state_fidelity\n", "from paddle_quantum.utils import partial_trace, dagger, state_fidelity\n",
"from paddle import complex\n", "from tqdm import tqdm"
"from progressbar import *"
] ]
}, },
{ {
...@@ -235,27 +233,27 @@ ...@@ -235,27 +233,27 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 2,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"class QGAN(fluid.dygraph.Layer):\n", "class QGAN(paddle.nn.Layer):\n",
" def __init__(self):\n", " def __init__(self):\n",
" super(QGAN, self).__init__()\n", " super(QGAN, self).__init__()\n",
" \n", " \n",
" # 用以制备目标量子态的角度\n", " # 用以制备目标量子态的角度\n",
" target_omega_0 = 0.9 * np.pi\n", " target_omega_0 = 0.9 * np.pi\n",
" target_omega_1 = 0.2 * np.pi\n", " target_omega_1 = 0.2 * np.pi\n",
" self.target_omega = fluid.dygraph.to_variable(\n", " self.target_omega = paddle.to_tensor(\n",
" np.array([target_omega_0, target_omega_1], np.float64))\n", " np.array([target_omega_0, target_omega_1], np.float64))\n",
" \n", " \n",
" # 生成器和判别器电路的参数\n", " # 生成器和判别器电路的参数\n",
" self.gen_theta = self.create_parameter([9], \n", " self.gen_theta = self.create_parameter([9], \n",
" dtype=\"float64\", attr=fluid.initializer.Uniform(\n", " dtype=\"float64\", default_initializer=paddle.nn.initializer.Uniform(\n",
" low=0.0, high=np.pi, seed=7))\n", " low=0.0, high=np.pi))\n",
" self.disc_phi = self.create_parameter([9], \n", " self.disc_phi = self.create_parameter([9], \n",
" dtype=\"float64\", attr=fluid.initializer.Uniform(\n", " dtype=\"float64\", default_initializer=paddle.nn.initializer.Uniform(\n",
" low=0.0, high=np.pi, seed=8))\n", " low=0.0, high=np.pi))\n",
" \n", " \n",
" # 制备目标量子态\n", " # 制备目标量子态\n",
" cir = UAnsatz(3)\n", " cir = UAnsatz(3)\n",
...@@ -334,9 +332,8 @@ ...@@ -334,9 +332,8 @@
" 得到目标态的密度矩阵表示\n", " 得到目标态的密度矩阵表示\n",
" \"\"\"\n", " \"\"\"\n",
" state = self.target_state\n", " state = self.target_state\n",
" state = complex.reshape(state, [1] + state.shape)\n", " state = paddle.reshape(state, [1] + state.shape)\n",
" density_matrix = complex.matmul(\n", " density_matrix = paddle.matmul(dagger(state), state)\n",
" dagger(state), state)\n",
" state = partial_trace(density_matrix, 2, 4, 2)\n", " state = partial_trace(density_matrix, 2, 4, 2)\n",
"\n", "\n",
" return state.numpy()\n", " return state.numpy()\n",
...@@ -345,11 +342,9 @@ ...@@ -345,11 +342,9 @@
" \"\"\"\n", " \"\"\"\n",
" 得到生成态的密度矩阵表示\n", " 得到生成态的密度矩阵表示\n",
" \"\"\"\n", " \"\"\"\n",
" state = self.generator(\n", " state = self.generator(self.gen_theta).run_state_vector()\n",
" self.gen_theta).run_state_vector()\n", " state = paddle.reshape(state, [1] + state.shape)\n",
" state = complex.reshape(state, [1] + state.shape)\n", " density_matrix = paddle.matmul(dagger(state), state)\n",
" density_matrix = complex.matmul(\n",
" dagger(state), state)\n",
" state = partial_trace(density_matrix, 2, 4, 2)\n", " state = partial_trace(density_matrix, 2, 4, 2)\n",
"\n", "\n",
" return state.numpy()" " return state.numpy()"
...@@ -359,19 +354,19 @@ ...@@ -359,19 +354,19 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"接下来我们使用 PaddlePaddle 的动态图机制来训练我们的模型。" "接下来我们使用 PaddlePaddle 来训练我们的模型。"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Training: 100% |##########################| Elapsed Time: 0:01:57 Time: 0:01:57\r" "Training: 100%|#################################################| 1050/1050 [01:27<00:00, 12.01it/s]\n"
] ]
}, },
{ {
...@@ -379,23 +374,16 @@ ...@@ -379,23 +374,16 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"the density matrix of the target state:\n", "the density matrix of the target state:\n",
"[[0.02447174+0.j 0.125 +0.09081782j]\n", "[[0.02447174+0.00000000e+00j 0.125 +9.08178160e-02j]\n",
" [0.125 -0.09081782j 0.97552826+0.j ]] \n", " [0.125 -9.08178160e-02j 0.97552826+5.16498656e-18j]] \n",
"\n", "\n",
"the density matrix of the generated state:\n", "the density matrix of the generated state:\n",
"[[0.01664936+0.j 0.03736201+0.11797786j]\n", "[[0.0244643 -5.29696618e-19j 0.12657544+8.85689120e-02j]\n",
" [0.03736201-0.11797786j 0.98335064+0.j ]] \n", " [0.12657544-8.85689120e-02j 0.9755357 -2.82739625e-19j]] \n",
"\n", "\n",
"the distance between these two quantum states is 0.0169585492051749 \n", "the distance between these two quantum states is 1.5079277656078345e-05 \n",
"\n", "\n",
"the fidelity between these two quantum states is 0.9952202066208862\n" "the fidelity between these two quantum states is 0.9999962306522913\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
] ]
} }
], ],
...@@ -411,64 +399,59 @@ ...@@ -411,64 +399,59 @@
"\n", "\n",
"# 用来记录loss值的变化\n", "# 用来记录loss值的变化\n",
"loss_history = list()\n", "loss_history = list()\n",
"with fluid.dygraph.guard():\n", "paddle.seed(18)\n",
" gan_demo = QGAN()\n", "gan_demo = QGAN()\n",
" optimizer = fluid.optimizer.SGDOptimizer(\n", "optimizer = paddle.optimizer.SGD(learning_rate=LR, parameters=gan_demo.parameters())\n",
" learning_rate=LR, parameter_list=gan_demo.parameters())\n", "pbar = tqdm(desc=\"Training: \", total=ITR * (ITR1 + ITR2), ncols=100, ascii=True)\n",
" widgets = ['Training: ', Percentage(), ' ', \n", "for itr0 in range(ITR):\n",
" Bar('#'), ' ', Timer(), ' ', ETA()]\n", "\n",
" pbar = ProgressBar(widgets=widgets, maxval=ITR * 70).start()\n", " # 记录判别器loss值的变化\n",
" for itr0 in range(ITR):\n", " loss_disc_history = list()\n",
" \n", "\n",
" # 记录判别器loss值的变化\n", " # 训练判别器\n",
" loss_disc_history = list()\n", " for itr1 in range(ITR1):\n",
" \n", " pbar.update(1)\n",
" # 训练判别器\n", " loss_disc = gan_demo('disc')\n",
" for itr1 in range(ITR1):\n", " loss_disc.backward()\n",
" pbar.update(itr0 * (ITR1 + ITR2) + itr1)\n", " optimizer.minimize(loss_disc, parameters=[gan_demo.disc_phi],\n",
" loss_disc = gan_demo('disc')\n", " no_grad_set=[gan_demo.gen_theta])\n",
" loss_disc.backward()\n", " gan_demo.clear_gradients()\n",
" optimizer.minimize(loss_disc, parameter_list\n", " loss_disc_history.append(loss_disc.numpy()[0])\n",
" =[gan_demo.disc_phi], \n", "\n",
" no_grad_set=[gan_demo.gen_theta])\n", " # 记录生成器loss值的变化\n",
" gan_demo.clear_gradients()\n", " loss_gen_history = list()\n",
" loss_disc_history.append(loss_disc.numpy()[0])\n", "\n",
"\n", " # 训练生成器\n",
" # 记录生成器loss值的变化\n", " for itr2 in range(ITR2):\n",
" loss_gen_history = list()\n", " pbar.update(1)\n",
" \n", " loss_gen = gan_demo('gen')\n",
" # 训练生成器\n", " loss_gen.backward()\n",
" for itr2 in range(ITR2):\n", " optimizer.minimize(loss_gen, parameters=[gan_demo.gen_theta],\n",
" pbar.update(itr0 * (ITR1 + ITR2) + ITR1 + itr2)\n", " no_grad_set=[gan_demo.disc_phi])\n",
" loss_gen = gan_demo('gen')\n", " optimizer.clear_grad()\n",
" loss_gen.backward()\n", " loss_gen_history.append(loss_gen.numpy()[0])\n",
" optimizer.minimize(loss_gen, parameter_list\n", "\n",
" =[gan_demo.gen_theta], \n", " loss_history.append((loss_disc_history, loss_gen_history))\n",
" no_grad_set=[gan_demo.disc_phi])\n", "pbar.close()\n",
" gan_demo.clear_gradients()\n", "\n",
" loss_gen_history.append(loss_gen.numpy()[0])\n", "# 得到目标量子态\n",
"\n", "target_state = gan_demo.get_target_state()\n",
" loss_history.append((loss_disc_history, loss_gen_history))\n", "\n",
" pbar.finish()\n", "# 得到生成器最终生成的量子态\n",
" \n", "gen_state = gan_demo.get_generated_state()\n",
" # 得到目标量子态\n", "print(\"the density matrix of the target state:\")\n",
" target_state = gan_demo.get_target_state()\n", "print(target_state, \"\\n\")\n",
" \n", "print(\"the density matrix of the generated state:\")\n",
" # 得到生成器最终生成的量子态\n", "print(gen_state, \"\\n\")\n",
" gen_state = gan_demo.get_generated_state()\n", "\n",
" print(\"the density matrix of the target state:\")\n", "# 计算两个量子态之间的距离,\n",
" print(target_state, \"\\n\")\n", "# 这里的距离定义为 tr[(target_state-gen_state)^2]\n",
" print(\"the density matrix of the generated state:\")\n", "distance = np.trace(np.matmul(target_state-gen_state, \n",
" print(gen_state, \"\\n\")\n", " target_state-gen_state)).real\n",
" \n", "# 计算两个量子态的保真度\n",
" # 计算两个量子态之间的距离,\n", "fidelity = state_fidelity(target_state, gen_state)\n",
" # 这里的距离定义为tr[(target_state-gen_state)^2]\n", "print(\"the distance between these two quantum states is\", distance, \"\\n\")\n",
" distance = np.trace(np.matmul(target_state-gen_state, \n", "print(\"the fidelity between these two quantum states is\", fidelity)"
" target_state-gen_state)).real\n",
" # 计算两个量子态的保真度\n",
" fidelity = state_fidelity(target_state, gen_state)\n",
" print(\"the distance between these two quantum states is\", distance, \"\\n\")\n",
" print(\"the fidelity between these two quantum states is\", fidelity)"
] ]
}, },
{ {
...@@ -496,7 +479,7 @@ ...@@ -496,7 +479,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 4,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -514,12 +497,12 @@ ...@@ -514,12 +497,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 5,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 2 Axes>" "<Figure size 432x288 with 2 Axes>"
] ]
...@@ -578,6 +561,8 @@ ...@@ -578,6 +561,8 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"_______\n",
"\n",
"## 参考文献" "## 参考文献"
] ]
}, },
...@@ -609,7 +594,7 @@ ...@@ -609,7 +594,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.8.5" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -231,11 +231,9 @@ ...@@ -231,11 +231,9 @@
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import paddle\n", "import paddle\n",
"from paddle import fluid\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import partial_trace, dagger, state_fidelity\n", "from paddle_quantum.utils import partial_trace, dagger, state_fidelity\n",
"from paddle import complex\n", "from tqdm import tqdm"
"from progressbar import *"
] ]
}, },
{ {
...@@ -256,23 +254,23 @@ ...@@ -256,23 +254,23 @@
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class QGAN(fluid.dygraph.Layer):\n", "class QGAN(paddle.nn.Layer):\n",
" def __init__(self):\n", " def __init__(self):\n",
" super(QGAN, self).__init__()\n", " super(QGAN, self).__init__()\n",
" \n", " \n",
" # The angle used to prepare the target quantum state\n", " # The angle used to prepare the target quantum state\n",
" target_omega_0 = 0.9 * np.pi\n", " target_omega_0 = 0.9 * np.pi\n",
" target_omega_1 = 0.2 * np.pi\n", " target_omega_1 = 0.2 * np.pi\n",
" self.target_omega = fluid.dygraph.to_variable(\n", " self.target_omega = paddle.to_tensor(\n",
" np.array([target_omega_0, target_omega_1], np.float64))\n", " np.array([target_omega_0, target_omega_1], np.float64))\n",
" \n", " \n",
" # Generator and discriminator circuit parameters\n", " # Generator and discriminator circuit parameters\n",
" self.gen_theta = self.create_parameter([9], \n", " self.gen_theta = self.create_parameter([9], \n",
" dtype=\"float64\", attr=fluid.initializer.Uniform(\n", " dtype=\"float64\", default_initializer=paddle.nn.initializer.Uniform(\n",
" low=0.0, high=np.pi, seed=7))\n", " low=0.0, high=np.pi))\n",
" self.disc_phi = self.create_parameter([9], \n", " self.disc_phi = self.create_parameter([9], \n",
" dtype=\"float64\", attr=fluid.initializer.Uniform(\n", " dtype=\"float64\", default_initializer=paddle.nn.initializer.Uniform(\n",
" low=0.0, high=np.pi, seed=8))\n", " low=0.0, high=np.pi))\n",
" \n", " \n",
" # Prepare target quantum state\n", " # Prepare target quantum state\n",
" cir = UAnsatz(3)\n", " cir = UAnsatz(3)\n",
...@@ -305,78 +303,76 @@ ...@@ -305,78 +303,76 @@
" return cir\n", " return cir\n",
"\n", "\n",
" def disc_target_as_target(self):\n", " def disc_target_as_target(self):\n",
" \"\"\"\n", " \"\"\"\n",
" The probability that the discriminator judges the target state as the target state\n", " The probability that the discriminator judges the target state as the target state\n",
" \"\"\"\n", " \"\"\"\n",
" # Discriminator circuit\n", " # Discriminator circuit\n",
" cir = self.discriminator(self.disc_phi)\n", " cir = self.discriminator(self.disc_phi)\n",
" cir.run_state_vector(self.target_state)\n", " cir.run_state_vector(self.target_state)\n",
" \n",
" # The judgment result of the discriminator on the target state\n",
" target_disc_output = cir.expecval([[1.0,'z2']])\n",
" prob_as_target = (target_disc_output + 1) / 2\n",
"\n", "\n",
" return prob_as_target\n", " # The judgment result of the discriminator on the target state\n",
" target_disc_output = cir.expecval([[1.0,'z2']])\n",
" prob_as_target = (target_disc_output + 1) / 2\n",
"\n",
" return prob_as_target\n",
"\n", "\n",
" def disc_gen_as_target(self):\n", " def disc_gen_as_target(self):\n",
" \"\"\"\n", " \"\"\"\n",
" The probability that the discriminator judges the generated state as the target state\n", " The probability that the discriminator judges the generated state as the target state\n",
" \"\"\"\n", " \"\"\"\n",
" # Get the quantum state generated by the generator\n", " # Get the quantum state generated by the generator\n",
" gen_state = self.generator(\n", " gen_state = self.generator(\n",
" self.gen_theta).run_state_vector()\n", " self.gen_theta).run_state_vector()\n",
" # Discriminator circuit\n", " # Discriminator circuit\n",
" cir = self.discriminator(self.disc_phi)\n", " cir = self.discriminator(self.disc_phi)\n",
" cir.run_state_vector(gen_state)\n", " cir.run_state_vector(gen_state)\n",
" # The judgment result of the discriminator on the generated state\n", " # The judgment result of the discriminator on the generated state\n",
" gen_disc_output = cir.expecval([[1.0,'z2']])\n", " gen_disc_output = cir.expecval([[1.0,'z2']])\n",
" prob_as_target = (gen_disc_output + 1) / 2\n", " prob_as_target = (gen_disc_output + 1) / 2\n",
" \n", "\n",
" return prob_as_target\n", " return prob_as_target\n",
"\n", "\n",
" def forward(self, model_name):\n", " def forward(self, model_name):\n",
" if model_name =='gen':\n", " if model_name =='gen':\n",
" # Calculate the loss function of the generator, the interval of the loss value is [-1, 0],\n", " # Calculate the loss function of the generator, the interval of the loss value is [-1, 0],\n",
" # 0 means extremely poor generation effect, -1 means excellent generation effect\n", " # 0 means extremely poor generation effect, -1 means excellent generation effect\n",
" loss = -1 * self.disc_gen_as_target()\n", " loss = -1 * self.disc_gen_as_target()\n",
" else:\n", " else:\n",
" # Calculate the loss function of the discriminator, the loss value range is [-1, 1],\n", " # Calculate the loss function of the discriminator, the loss value range is [-1, 1],\n",
" # -1 means perfect distinction, 0 means indistinguishable, 1 means inverted distinction\n", " # -1 means perfect distinction, 0 means indistinguishable, 1 means inverted distinction\n",
" loss = self.disc_gen_as_target() - self.disc_target_as_target()\n", " loss = self.disc_gen_as_target() - self.disc_target_as_target()\n",
"\n", "\n",
" return loss\n", " return loss\n",
"\n", "\n",
" def get_target_state(self):\n", " def get_target_state(self):\n",
" \"\"\"\n", " \"\"\"\n",
" Get the density matrix representation of the target state\n", " Get the density matrix representation of the target state\n",
" \"\"\"\n", " \"\"\"\n",
" state = self.target_state\n", " state = self.target_state\n",
" state = complex.reshape(state, [1] + state.shape)\n", " state = paddle.reshape(state, [1] + state.shape)\n",
" density_matrix = complex.matmul(\n", " density_matrix = paddle.matmul(dagger(state), state)\n",
" dagger(state), state)\n", " state = partial_trace(density_matrix, 2, 4, 2)\n",
" state = partial_trace(density_matrix, 2, 4, 2)\n",
"\n", "\n",
" return state.numpy()\n", " return state.numpy()\n",
"\n", "\n",
" def get_generated_state(self):\n", " def get_generated_state(self):\n",
" \"\"\"\n", " \"\"\"\n",
" Get the density matrix representation of the generated state\n", " Get the density matrix representation of the generated state\n",
" \"\"\"\n", " \"\"\"\n",
" state = self.generator(\n", " state = self.generator(\n",
" self.gen_theta).run_state_vector()\n", " self.gen_theta).run_state_vector()\n",
" state = complex.reshape(state, [1] + state.shape)\n", " state = paddle.reshape(state, [1] + state.shape)\n",
" density_matrix = complex.matmul(\n", " density_matrix = paddle.matmul(dagger(state), state)\n",
" dagger(state), state)\n", " state = partial_trace(density_matrix, 2, 4, 2)\n",
" state = partial_trace(density_matrix, 2, 4, 2)\n",
"\n", "\n",
" return state.numpy()" " return state.numpy()"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Next, we use PaddlePaddle's dynamic graph mechanism to train our model." "Next, we use PaddlePaddle to train our model."
] ]
}, },
{ {
...@@ -393,7 +389,7 @@ ...@@ -393,7 +389,7 @@
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Training:100%|##############################|Elapsed Time: 0:02:19Time: 0:02:19\r" "Training: 100%|#################################################| 1050/1050 [01:31<00:00, 11.51it/s]\n"
] ]
}, },
{ {
...@@ -401,23 +397,16 @@ ...@@ -401,23 +397,16 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"the density matrix of the target state:\n", "the density matrix of the target state:\n",
"[[0.02447174+0.j 0.125 +0.09081782j]\n", "[[0.02447174+0.00000000e+00j 0.125 +9.08178160e-02j]\n",
" [0.125 -0.09081782j 0.97552826+0.j ]] \n", " [0.125 -9.08178160e-02j 0.97552826+5.16498656e-18j]] \n",
"\n", "\n",
"the density matrix of the generated state:\n", "the density matrix of the generated state:\n",
"[[0.01664936+0.j 0.03736201+0.11797786j]\n", "[[0.0244643 -5.29696618e-19j 0.12657544+8.85689120e-02j]\n",
" [0.03736201-0.11797786j 0.98335064+0.j ]] \n", " [0.12657544-8.85689120e-02j 0.9755357 -2.82739625e-19j]] \n",
"\n", "\n",
"the distance between these two quantum states is 0.01695854920517497 \n", "the distance between these two quantum states is 1.5079277656078345e-05 \n",
"\n", "\n",
"the fidelity between these two quantum states is 0.9952202063690136\n" "the fidelity between these two quantum states is 0.9999962306522913\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
] ]
} }
], ],
...@@ -433,64 +422,61 @@ ...@@ -433,64 +422,61 @@
"\n", "\n",
"# Used to record the change of loss value\n", "# Used to record the change of loss value\n",
"loss_history = list()\n", "loss_history = list()\n",
"with fluid.dygraph.guard():\n", "paddle.seed(18)\n",
" gan_demo = QGAN()\n", "gan_demo = QGAN()\n",
" optimizer = fluid.optimizer.SGDOptimizer(\n", "optimizer = paddle.optimizer.SGD(learning_rate=LR, parameters=gan_demo.parameters())\n",
" learning_rate=LR, parameter_list=gan_demo.parameters())\n", "pbar = tqdm(desc=\"Training: \", total=ITR * (ITR1 + ITR2), ncols=100, ascii=True)\n",
" widgets = ['Training:', Percentage(), '',\n", "for itr0 in range(ITR):\n",
" Bar('#'), '', Timer(),'', ETA()]\n", "\n",
" pbar = ProgressBar(widgets=widgets, maxval=ITR * 70).start()\n", " # Record the change in the loss value of the discriminator\n",
" for itr0 in range(ITR):\n", " loss_disc_history = list()\n",
" \n", "\n",
" # Record the change in the loss value of the discriminator\n", " # Train the discriminator\n",
" loss_disc_history = list()\n", " for itr1 in range(ITR1):\n",
" \n", " pbar.update(1)\n",
" # Train the discriminator\n", " loss_disc = gan_demo('disc')\n",
" for itr1 in range(ITR1):\n", " loss_disc.backward()\n",
" pbar.update(itr0 * (ITR1 + ITR2) + itr1)\n", " optimizer.minimize(loss_disc, parameters\n",
" loss_disc = gan_demo('disc')\n", " =[gan_demo.disc_phi],\n",
" loss_disc.backward()\n", " no_grad_set=[gan_demo.gen_theta])\n",
" optimizer.minimize(loss_disc, parameter_list\n", " gan_demo.clear_gradients()\n",
" =[gan_demo.disc_phi],\n", " loss_disc_history.append(loss_disc.numpy()[0])\n",
" no_grad_set=[gan_demo.gen_theta])\n", "\n",
" gan_demo.clear_gradients()\n", " # Record the change of the generator loss value\n",
" loss_disc_history.append(loss_disc.numpy()[0])\n", " loss_gen_history = list()\n",
"\n", "\n",
" # Record the change of the generator loss value\n", " # Training generator\n",
" loss_gen_history = list()\n", " for itr2 in range(ITR2):\n",
" \n", " pbar.update(1)\n",
" # Training generator\n", " loss_gen = gan_demo('gen')\n",
" for itr2 in range(ITR2):\n", " loss_gen.backward()\n",
" pbar.update(itr0 * (ITR1 + ITR2) + ITR1 + itr2)\n", " optimizer.minimize(loss_gen, parameters\n",
" loss_gen = gan_demo('gen')\n", " =[gan_demo.gen_theta],\n",
" loss_gen.backward()\n", " no_grad_set=[gan_demo.disc_phi])\n",
" optimizer.minimize(loss_gen, parameter_list\n", " optimizer.clear_grad()\n",
" =[gan_demo.gen_theta],\n", " loss_gen_history.append(loss_gen.numpy()[0])\n",
" no_grad_set=[gan_demo.disc_phi])\n", "\n",
" gan_demo.clear_gradients()\n", " loss_history.append((loss_disc_history, loss_gen_history))\n",
" loss_gen_history.append(loss_gen.numpy()[0])\n", "pbar.close()\n",
"\n", "\n",
" loss_history.append((loss_disc_history, loss_gen_history))\n", "# Get the target quantum state\n",
" pbar.finish()\n", "target_state = gan_demo.get_target_state()\n",
" \n", "\n",
" # Get the target quantum state\n", "# Get the final quantum state generated by the generator\n",
" target_state = gan_demo.get_target_state()\n", "gen_state = gan_demo.get_generated_state()\n",
" \n", "print(\"the density matrix of the target state:\")\n",
" # Get the final quantum state generated by the generator\n", "print(target_state, \"\\n\")\n",
" gen_state = gan_demo.get_generated_state()\n", "print(\"the density matrix of the generated state:\")\n",
" print(\"the density matrix of the target state:\")\n", "print(gen_state, \"\\n\")\n",
" print(target_state, \"\\n\")\n", "\n",
" print(\"the density matrix of the generated state:\")\n", "# Calculate the distance between two quantum states,\n",
" print(gen_state, \"\\n\")\n", "# The distance here is defined as tr[(target_state-gen_state)^2]\n",
" \n", "distance = np.trace(np.matmul(target_state-gen_state,\n",
" # Calculate the distance between two quantum states,\n", " target_state-gen_state)).real\n",
" # The distance here is defined as tr[(target_state-gen_state)^2]\n", "# Calculate the fidelity of two quantum states\n",
" distance = np.trace(np.matmul(target_state-gen_state,\n", "fidelity = state_fidelity(target_state, gen_state)\n",
" target_state-gen_state)).real\n", "print(\"the distance between these two quantum states is\", distance, \"\\n\")\n",
" # Calculate the fidelity of two quantum states\n", "print(\"the fidelity between these two quantum states is\", fidelity)"
" fidelity = state_fidelity(target_state, gen_state)\n",
" print(\"the distance between these two quantum states is\", distance, \"\\n\")\n",
" print(\"the fidelity between these two quantum states is\", fidelity)"
] ]
}, },
{ {
...@@ -518,7 +504,7 @@ ...@@ -518,7 +504,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": 4,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -536,12 +522,12 @@ ...@@ -536,12 +522,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": 5,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 2 Axes>" "<Figure size 432x288 with 2 Axes>"
] ]
...@@ -600,6 +586,8 @@ ...@@ -600,6 +586,8 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"_______\n",
"\n",
"## References" "## References"
] ]
}, },
...@@ -631,7 +619,7 @@ ...@@ -631,7 +619,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.8.5" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
tutorial/Q-GAN/figures/loss.gif

130.5 KB | W: | H:

tutorial/Q-GAN/figures/loss.gif

77.8 KB | W: | H:

tutorial/Q-GAN/figures/loss.gif
tutorial/Q-GAN/figures/loss.gif
tutorial/Q-GAN/figures/loss.gif
tutorial/Q-GAN/figures/loss.gif
  • 2-up
  • Swipe
  • Onion skin
...@@ -371,21 +371,20 @@ ...@@ -371,21 +371,20 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:00:43.231250Z", "end_time": "2021-02-22T11:04:55.556042Z",
"start_time": "2021-01-09T07:00:38.262611Z" "start_time": "2021-02-22T11:04:55.546040Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"# 加载量桨、飞桨的相关模块\n", "# 加载量桨、飞桨的相关模块\n",
"from paddle import fluid\n", "import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import pauli_str_to_matrix\n", "from paddle_quantum.utils import pauli_str_to_matrix\n",
"\n", "\n",
"# 加载额外需要用到的包\n", "# 加载额外需要用到的包\n",
"import numpy as np\n", "import numpy as np\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"%config InlineBackend.figure_format = 'svg'\n",
"import networkx as nx" "import networkx as nx"
] ]
}, },
...@@ -401,217 +400,22 @@ ...@@ -401,217 +400,22 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:01:12.884308Z", "end_time": "2021-02-22T11:04:58.341557Z",
"start_time": "2021-01-09T07:01:12.683078Z" "start_time": "2021-02-22T11:04:58.266794Z"
} }
}, },
"outputs": [ "outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/v_yusizhuo/opt/anaconda3/envs/pq2.0.1/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n",
" and should_run_async(code)\n"
]
},
{ {
"data": { "data": {
"image/svg+xml": [ "image/png": "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\n",
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Created with matplotlib (https://matplotlib.org/) -->\n",
"<svg height=\"231.84pt\" version=\"1.1\" viewBox=\"0 0 349.2 231.84\" width=\"349.2pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
" <metadata>\n",
" <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
" <cc:Work>\n",
" <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
" <dc:date>2021-01-09T15:01:12.860328</dc:date>\n",
" <dc:format>image/svg+xml</dc:format>\n",
" <dc:creator>\n",
" <cc:Agent>\n",
" <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\n",
" </cc:Agent>\n",
" </dc:creator>\n",
" </cc:Work>\n",
" </rdf:RDF>\n",
" </metadata>\n",
" <defs>\n",
" <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n",
" </defs>\n",
" <g id=\"figure_1\">\n",
" <g id=\"patch_1\">\n",
" <path d=\"M 0 231.84 \n",
"L 349.2 231.84 \n",
"L 349.2 0 \n",
"L 0 0 \n",
"z\n",
"\" style=\"fill:none;\"/>\n",
" </g>\n",
" <g id=\"axes_1\">\n",
" <g id=\"LineCollection_1\">\n",
" <path clip-path=\"url(#pede19378b3)\" d=\"M 294.171429 115.92 \n",
"L 174.599995 38.262857 \n",
"\" style=\"fill:none;stroke:#000000;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#pede19378b3)\" d=\"M 294.171429 115.92 \n",
"L 174.600001 193.577143 \n",
"\" style=\"fill:none;stroke:#000000;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#pede19378b3)\" d=\"M 174.599995 38.262857 \n",
"L 55.028571 115.920007 \n",
"\" style=\"fill:none;stroke:#000000;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#pede19378b3)\" d=\"M 55.028571 115.920007 \n",
"L 174.600001 193.577143 \n",
"\" style=\"fill:none;stroke:#000000;stroke-width:2;\"/>\n",
" </g>\n",
" <g id=\"PathCollection_1\">\n",
" <defs>\n",
" <path d=\"M 0 22.36068 \n",
"C 5.930122 22.36068 11.618159 20.004617 15.811388 15.811388 \n",
"C 20.004617 11.618159 22.36068 5.930122 22.36068 0 \n",
"C 22.36068 -5.930122 20.004617 -11.618159 15.811388 -15.811388 \n",
"C 11.618159 -20.004617 5.930122 -22.36068 0 -22.36068 \n",
"C -5.930122 -22.36068 -11.618159 -20.004617 -15.811388 -15.811388 \n",
"C -20.004617 -11.618159 -22.36068 -5.930122 -22.36068 0 \n",
"C -22.36068 5.930122 -20.004617 11.618159 -15.811388 15.811388 \n",
"C -11.618159 20.004617 -5.930122 22.36068 0 22.36068 \n",
"z\n",
"\" id=\"m71159471ec\" style=\"stroke:#1f78b4;\"/>\n",
" </defs>\n",
" <g clip-path=\"url(#pede19378b3)\">\n",
" <use style=\"fill:#1f78b4;stroke:#1f78b4;\" x=\"294.171429\" xlink:href=\"#m71159471ec\" y=\"115.92\"/>\n",
" <use style=\"fill:#1f78b4;stroke:#1f78b4;\" x=\"174.599995\" xlink:href=\"#m71159471ec\" y=\"38.262857\"/>\n",
" <use style=\"fill:#1f78b4;stroke:#1f78b4;\" x=\"55.028571\" xlink:href=\"#m71159471ec\" y=\"115.920007\"/>\n",
" <use style=\"fill:#1f78b4;stroke:#1f78b4;\" x=\"174.600001\" xlink:href=\"#m71159471ec\" y=\"193.577143\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_1\">\n",
" <g clip-path=\"url(#pede19378b3)\">\n",
" <!-- 0 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(287.213616 121.43875)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 46 36.53125 \n",
"Q 46 50.203125 43.4375 55.78125 \n",
"Q 40.875 61.375 34.8125 61.375 \n",
"Q 28.765625 61.375 26.171875 55.78125 \n",
"Q 23.578125 50.203125 23.578125 36.53125 \n",
"Q 23.578125 22.703125 26.171875 17.03125 \n",
"Q 28.765625 11.375 34.8125 11.375 \n",
"Q 40.828125 11.375 43.40625 17.03125 \n",
"Q 46 22.703125 46 36.53125 \n",
"z\n",
"M 64.796875 36.375 \n",
"Q 64.796875 18.265625 56.984375 8.421875 \n",
"Q 49.171875 -1.421875 34.8125 -1.421875 \n",
"Q 20.40625 -1.421875 12.59375 8.421875 \n",
"Q 4.78125 18.265625 4.78125 36.375 \n",
"Q 4.78125 54.546875 12.59375 64.375 \n",
"Q 20.40625 74.21875 34.8125 74.21875 \n",
"Q 49.171875 74.21875 56.984375 64.375 \n",
"Q 64.796875 54.546875 64.796875 36.375 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-48\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_2\">\n",
" <g clip-path=\"url(#pede19378b3)\">\n",
" <!-- 1 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(167.642182 43.781607)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 11.71875 12.984375 \n",
"L 28.328125 12.984375 \n",
"L 28.328125 60.109375 \n",
"L 11.28125 56.59375 \n",
"L 11.28125 69.390625 \n",
"L 28.21875 72.90625 \n",
"L 46.09375 72.90625 \n",
"L 46.09375 12.984375 \n",
"L 62.703125 12.984375 \n",
"L 62.703125 0 \n",
"L 11.71875 0 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-49\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_3\">\n",
" <g clip-path=\"url(#pede19378b3)\">\n",
" <!-- 2 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(48.070759 121.438757)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 28.8125 13.8125 \n",
"L 60.890625 13.8125 \n",
"L 60.890625 0 \n",
"L 7.90625 0 \n",
"L 7.90625 13.8125 \n",
"L 34.515625 37.3125 \n",
"Q 38.09375 40.53125 39.796875 43.609375 \n",
"Q 41.5 46.6875 41.5 50 \n",
"Q 41.5 55.125 38.0625 58.25 \n",
"Q 34.625 61.375 28.90625 61.375 \n",
"Q 24.515625 61.375 19.28125 59.5 \n",
"Q 14.0625 57.625 8.109375 53.90625 \n",
"L 8.109375 69.921875 \n",
"Q 14.453125 72.015625 20.65625 73.109375 \n",
"Q 26.859375 74.21875 32.8125 74.21875 \n",
"Q 45.90625 74.21875 53.15625 68.453125 \n",
"Q 60.40625 62.703125 60.40625 52.390625 \n",
"Q 60.40625 46.4375 57.328125 41.28125 \n",
"Q 54.25 36.140625 44.390625 27.484375 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-50\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-50\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_4\">\n",
" <g clip-path=\"url(#pede19378b3)\">\n",
" <!-- 3 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(167.642189 199.095893)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 46.578125 39.3125 \n",
"Q 53.953125 37.40625 57.78125 32.6875 \n",
"Q 61.625 27.984375 61.625 20.703125 \n",
"Q 61.625 9.859375 53.3125 4.21875 \n",
"Q 45.015625 -1.421875 29.109375 -1.421875 \n",
"Q 23.484375 -1.421875 17.84375 -0.515625 \n",
"Q 12.203125 0.390625 6.6875 2.203125 \n",
"L 6.6875 16.703125 \n",
"Q 11.96875 14.0625 17.15625 12.71875 \n",
"Q 22.359375 11.375 27.390625 11.375 \n",
"Q 34.859375 11.375 38.84375 13.953125 \n",
"Q 42.828125 16.546875 42.828125 21.390625 \n",
"Q 42.828125 26.375 38.75 28.9375 \n",
"Q 34.671875 31.5 26.703125 31.5 \n",
"L 19.1875 31.5 \n",
"L 19.1875 43.609375 \n",
"L 27.09375 43.609375 \n",
"Q 34.1875 43.609375 37.640625 45.828125 \n",
"Q 41.109375 48.046875 41.109375 52.59375 \n",
"Q 41.109375 56.78125 37.734375 59.078125 \n",
"Q 34.375 61.375 28.21875 61.375 \n",
"Q 23.6875 61.375 19.046875 60.34375 \n",
"Q 14.40625 59.328125 9.8125 57.328125 \n",
"L 9.8125 71.09375 \n",
"Q 15.375 72.65625 20.84375 73.4375 \n",
"Q 26.3125 74.21875 31.59375 74.21875 \n",
"Q 45.796875 74.21875 52.84375 69.546875 \n",
"Q 59.90625 64.890625 59.90625 55.515625 \n",
"Q 59.90625 49.125 56.53125 45.046875 \n",
"Q 53.171875 40.96875 46.578125 39.3125 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-51\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-51\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <defs>\n",
" <clipPath id=\"pede19378b3\">\n",
" <rect height=\"217.44\" width=\"334.8\" x=\"7.2\" y=\"7.2\"/>\n",
" </clipPath>\n",
" </defs>\n",
"</svg>\n"
],
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -659,8 +463,8 @@ ...@@ -659,8 +463,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:01:33.911138Z", "end_time": "2021-02-22T11:05:01.414498Z",
"start_time": "2021-01-09T07:01:33.901933Z" "start_time": "2021-02-22T11:05:01.409511Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -699,8 +503,8 @@ ...@@ -699,8 +503,8 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:01:57.485432Z", "end_time": "2021-02-22T11:05:03.494792Z",
"start_time": "2021-01-09T07:01:57.475788Z" "start_time": "2021-02-22T11:05:03.488812Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -757,8 +561,8 @@ ...@@ -757,8 +561,8 @@
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:02:33.523693Z", "end_time": "2021-02-22T11:05:09.921594Z",
"start_time": "2021-01-09T07:02:33.508316Z" "start_time": "2021-02-22T11:05:09.914611Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -811,24 +615,27 @@ ...@@ -811,24 +615,27 @@
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:03:00.576339Z", "end_time": "2021-02-22T11:08:23.218571Z",
"start_time": "2021-01-09T07:03:00.564735Z" "start_time": "2021-02-22T11:08:23.211589Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Net(fluid.dygraph.Layer):\n", "class Net(paddle.nn.Layer):\n",
" def __init__(\n", " def __init__(\n",
" self,\n", " self,\n",
" p,\n", " p,\n",
" param_attr=fluid.initializer.Uniform(low=0.0, high=np.pi, seed=1024),\n",
" dtype=\"float64\",\n", " dtype=\"float64\",\n",
" ):\n", " ):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
"\n", "\n",
" self.p = p\n", " self.p = p\n",
" self.gamma = self.create_parameter(shape=[self.p], attr=param_attr, dtype=dtype, is_bias=False)\n", " self.gamma = self.create_parameter(shape=[self.p], \n",
" self.beta = self.create_parameter(shape=[self.p], attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*np.pi),\n",
" dtype=dtype, is_bias=False)\n",
" self.beta = self.create_parameter(shape=[self.p], \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*np.pi),\n",
" dtype=dtype, is_bias=False)\n",
"\n", "\n",
" def forward(self):\n", " def forward(self):\n",
" # 定义 QAOA 的量子电路\n", " # 定义 QAOA 的量子电路\n",
...@@ -854,22 +661,23 @@ ...@@ -854,22 +661,23 @@
"execution_count": 7, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:03:34.844845Z", "end_time": "2021-02-22T11:10:08.324892Z",
"start_time": "2021-01-09T07:03:34.829959Z" "start_time": "2021-02-22T11:10:08.321896Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"p = 4 # 量子电路的层数\n", "p = 4 # 量子电路的层数\n",
"ITR = 120 # 训练迭代的次数\n", "ITR = 120 # 训练迭代的次数\n",
"LR = 0.1 # 基于梯度下降的优化方法的学习率" "LR = 0.1 # 基于梯度下降的优化方法的学习率\n",
"SEED = 1024 #设置全局随机数种子"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"这里,我们在飞桨动态图中优化上面定义的网络。\n", "这里,我们在飞桨中优化上面定义的网络。\n",
"\n" "\n"
] ]
}, },
...@@ -878,55 +686,55 @@ ...@@ -878,55 +686,55 @@
"execution_count": 8, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:04:33.677212Z", "end_time": "2021-02-22T11:11:28.060342Z",
"start_time": "2021-01-09T07:03:53.962377Z" "start_time": "2021-02-22T11:11:09.448098Z"
}, }
"scrolled": true
}, },
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 10 loss: -3.7473\n", "iter: 10 loss: -3.8886\n",
"iter: 20 loss: -3.9696\n", "iter: 20 loss: -3.9134\n",
"iter: 30 loss: -3.9539\n", "iter: 30 loss: -3.9659\n",
"iter: 40 loss: -3.9710\n", "iter: 40 loss: -3.9906\n",
"iter: 50 loss: -3.9930\n", "iter: 50 loss: -3.9979\n",
"iter: 60 loss: -3.9991\n", "iter: 60 loss: -3.9993\n",
"iter: 70 loss: -3.9984\n", "iter: 70 loss: -3.9998\n",
"iter: 80 loss: -3.9998\n", "iter: 80 loss: -3.9999\n",
"iter: 90 loss: -3.9998\n", "iter: 90 loss: -4.0000\n",
"iter: 100 loss: -4.0000\n", "iter: 100 loss: -4.0000\n",
"iter: 110 loss: -4.0000\n", "iter: 110 loss: -4.0000\n",
"iter: 120 loss: -4.0000\n", "iter: 120 loss: -4.0000\n",
"优化后的参数 gamma:\n", "优化后的参数 gamma:\n",
" [0.70063329 0.45026914 1.17355432 2.13276803]\n", " [3.14046713 0.73681226 4.99897226 0.46481489]\n",
"优化后的参数 beta:\n", "优化后的参数 beta:\n",
" [-0.02466894 -0.20348931 1.12024105 0.61099467]\n" " [0.82379898 2.50618308 4.85422542 1.90024859]\n"
] ]
} }
], ],
"source": [ "source": [
"with fluid.dygraph.guard():\n", "paddle.seed(SEED)\n",
" net = Net(p)\n", "\n",
" # 使用 Adam 优化器\n", "net = Net(p)\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "# 使用 Adam 优化器\n",
" # 梯度下降循环\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" for itr in range(1, ITR + 1):\n", "# 梯度下降循环\n",
" # 运行上面定义的网络\n", "for itr in range(1, ITR + 1):\n",
" loss, cir = net()\n", " # 运行上面定义的网络\n",
" # 计算梯度并优化\n", " loss, cir = net()\n",
" loss.backward()\n", " # 计算梯度并优化\n",
" opt.minimize(loss)\n", " loss.backward() \n",
" net.clear_gradients()\n", " opt.minimize(loss)\n",
" if itr % 10 == 0:\n", " opt.clear_grad()\n",
" print(\"iter:\", itr, \" loss:\", \"%.4f\" % loss.numpy())\n", " if itr % 10 == 0:\n",
"\n", " print(\"iter:\", itr, \" loss:\", \"%.4f\" % loss.numpy())\n",
" gamma_opt = net.gamma.numpy()\n", "\n",
" print(\"优化后的参数 gamma:\\n\", gamma_opt)\n", "gamma_opt = net.gamma.numpy()\n",
" beta_opt = net.beta.numpy()\n", "print(\"优化后的参数 gamma:\\n\", gamma_opt)\n",
" print(\"优化后的参数 beta:\\n\", beta_opt)" "beta_opt = net.beta.numpy()\n",
"print(\"优化后的参数 beta:\\n\", beta_opt)"
] ]
}, },
{ {
...@@ -951,1094 +759,14 @@ ...@@ -951,1094 +759,14 @@
"execution_count": 9, "execution_count": 9,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:04:38.467066Z", "end_time": "2021-02-22T11:11:31.577428Z",
"start_time": "2021-01-09T07:04:38.094519Z" "start_time": "2021-02-22T11:11:31.390862Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/svg+xml": [ "image/png": "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\n",
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Created with matplotlib (https://matplotlib.org/) -->\n",
"<svg height=\"277.968125pt\" version=\"1.1\" viewBox=\"0 0 385.78125 277.968125\" width=\"385.78125pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
" <metadata>\n",
" <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
" <cc:Work>\n",
" <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
" <dc:date>2021-01-09T15:04:38.342915</dc:date>\n",
" <dc:format>image/svg+xml</dc:format>\n",
" <dc:creator>\n",
" <cc:Agent>\n",
" <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\n",
" </cc:Agent>\n",
" </dc:creator>\n",
" </cc:Work>\n",
" </rdf:RDF>\n",
" </metadata>\n",
" <defs>\n",
" <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n",
" </defs>\n",
" <g id=\"figure_1\">\n",
" <g id=\"patch_1\">\n",
" <path d=\"M 0 277.968125 \n",
"L 385.78125 277.968125 \n",
"L 385.78125 0 \n",
"L 0 0 \n",
"z\n",
"\" style=\"fill:none;\"/>\n",
" </g>\n",
" <g id=\"axes_1\">\n",
" <g id=\"patch_2\">\n",
" <path d=\"M 43.78125 224.64 \n",
"L 378.58125 224.64 \n",
"L 378.58125 7.2 \n",
"L 43.78125 7.2 \n",
"z\n",
"\" style=\"fill:#ffffff;\"/>\n",
" </g>\n",
" <g id=\"patch_3\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 58.999432 224.64 \n",
"L 74.410249 224.64 \n",
"L 74.410249 224.64 \n",
"L 58.999432 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_4\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 78.262953 224.64 \n",
"L 93.67377 224.64 \n",
"L 93.67377 224.64 \n",
"L 78.262953 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_5\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 97.526474 224.64 \n",
"L 112.937291 224.64 \n",
"L 112.937291 224.64 \n",
"L 97.526474 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_6\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 116.789996 224.64 \n",
"L 132.200813 224.64 \n",
"L 132.200813 224.64 \n",
"L 116.789996 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_7\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 136.053517 224.64 \n",
"L 151.464334 224.64 \n",
"L 151.464334 224.64 \n",
"L 136.053517 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_8\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 155.317038 224.64 \n",
"L 170.727855 224.64 \n",
"L 170.727855 17.554286 \n",
"L 155.317038 17.554286 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_9\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 174.58056 224.64 \n",
"L 189.991377 224.64 \n",
"L 189.991377 224.64 \n",
"L 174.58056 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_10\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 193.844081 224.64 \n",
"L 209.254898 224.64 \n",
"L 209.254898 224.64 \n",
"L 193.844081 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_11\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 213.107602 224.64 \n",
"L 228.518419 224.64 \n",
"L 228.518419 224.64 \n",
"L 213.107602 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_12\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 232.371123 224.64 \n",
"L 247.78194 224.64 \n",
"L 247.78194 224.64 \n",
"L 232.371123 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_13\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 251.634645 224.64 \n",
"L 267.045462 224.64 \n",
"L 267.045462 24.708879 \n",
"L 251.634645 24.708879 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_14\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 270.898166 224.64 \n",
"L 286.308983 224.64 \n",
"L 286.308983 224.64 \n",
"L 270.898166 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_15\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 290.161687 224.64 \n",
"L 305.572504 224.64 \n",
"L 305.572504 224.64 \n",
"L 290.161687 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_16\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 309.425209 224.64 \n",
"L 324.836026 224.64 \n",
"L 324.836026 224.64 \n",
"L 309.425209 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_17\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 328.68873 224.64 \n",
"L 344.099547 224.64 \n",
"L 344.099547 224.64 \n",
"L 328.68873 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_18\">\n",
" <path clip-path=\"url(#p5520171445)\" d=\"M 347.952251 224.64 \n",
"L 363.363068 224.64 \n",
"L 363.363068 224.64 \n",
"L 347.952251 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"matplotlib.axis_1\">\n",
" <g id=\"xtick_1\">\n",
" <g id=\"line2d_1\">\n",
" <defs>\n",
" <path d=\"M 0 0 \n",
"L 0 3.5 \n",
"\" id=\"mc1fc8c99ed\" style=\"stroke:#000000;stroke-width:0.8;\"/>\n",
" </defs>\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"66.70484\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_1\">\n",
" <!-- 0000 -->\n",
" <g transform=\"translate(69.464215 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 31.78125 66.40625 \n",
"Q 24.171875 66.40625 20.328125 58.90625 \n",
"Q 16.5 51.421875 16.5 36.375 \n",
"Q 16.5 21.390625 20.328125 13.890625 \n",
"Q 24.171875 6.390625 31.78125 6.390625 \n",
"Q 39.453125 6.390625 43.28125 13.890625 \n",
"Q 47.125 21.390625 47.125 36.375 \n",
"Q 47.125 51.421875 43.28125 58.90625 \n",
"Q 39.453125 66.40625 31.78125 66.40625 \n",
"z\n",
"M 31.78125 74.21875 \n",
"Q 44.046875 74.21875 50.515625 64.515625 \n",
"Q 56.984375 54.828125 56.984375 36.375 \n",
"Q 56.984375 17.96875 50.515625 8.265625 \n",
"Q 44.046875 -1.421875 31.78125 -1.421875 \n",
"Q 19.53125 -1.421875 13.0625 8.265625 \n",
"Q 6.59375 17.96875 6.59375 36.375 \n",
"Q 6.59375 54.828125 13.0625 64.515625 \n",
"Q 19.53125 74.21875 31.78125 74.21875 \n",
"z\n",
"\" id=\"DejaVuSans-48\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_2\">\n",
" <g id=\"line2d_2\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"85.968362\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_2\">\n",
" <!-- 0001 -->\n",
" <g transform=\"translate(88.727737 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 12.40625 8.296875 \n",
"L 28.515625 8.296875 \n",
"L 28.515625 63.921875 \n",
"L 10.984375 60.40625 \n",
"L 10.984375 69.390625 \n",
"L 28.421875 72.90625 \n",
"L 38.28125 72.90625 \n",
"L 38.28125 8.296875 \n",
"L 54.390625 8.296875 \n",
"L 54.390625 0 \n",
"L 12.40625 0 \n",
"z\n",
"\" id=\"DejaVuSans-49\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_3\">\n",
" <g id=\"line2d_3\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"105.231883\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_3\">\n",
" <!-- 0010 -->\n",
" <g transform=\"translate(107.991258 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_4\">\n",
" <g id=\"line2d_4\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"124.495404\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_4\">\n",
" <!-- 0011 -->\n",
" <g transform=\"translate(127.254779 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_5\">\n",
" <g id=\"line2d_5\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"143.758925\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_5\">\n",
" <!-- 0100 -->\n",
" <g transform=\"translate(146.5183 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_6\">\n",
" <g id=\"line2d_6\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"163.022447\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_6\">\n",
" <!-- 0101 -->\n",
" <g transform=\"translate(165.781822 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_7\">\n",
" <g id=\"line2d_7\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"182.285968\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_7\">\n",
" <!-- 0110 -->\n",
" <g transform=\"translate(185.045343 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_8\">\n",
" <g id=\"line2d_8\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"201.549489\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_8\">\n",
" <!-- 0111 -->\n",
" <g transform=\"translate(204.308864 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_9\">\n",
" <g id=\"line2d_9\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"220.813011\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_9\">\n",
" <!-- 1000 -->\n",
" <g transform=\"translate(223.572386 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_10\">\n",
" <g id=\"line2d_10\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"240.076532\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_10\">\n",
" <!-- 1001 -->\n",
" <g transform=\"translate(242.835907 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_11\">\n",
" <g id=\"line2d_11\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"259.340053\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_11\">\n",
" <!-- 1010 -->\n",
" <g transform=\"translate(262.099428 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_12\">\n",
" <g id=\"line2d_12\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"278.603575\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_12\">\n",
" <!-- 1011 -->\n",
" <g transform=\"translate(281.36295 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_13\">\n",
" <g id=\"line2d_13\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"297.867096\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_13\">\n",
" <!-- 1100 -->\n",
" <g transform=\"translate(300.626471 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_14\">\n",
" <g id=\"line2d_14\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"317.130617\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_14\">\n",
" <!-- 1101 -->\n",
" <g transform=\"translate(319.889992 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_15\">\n",
" <g id=\"line2d_15\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"336.394138\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_15\">\n",
" <!-- 1110 -->\n",
" <g transform=\"translate(339.153513 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_16\">\n",
" <g id=\"line2d_16\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"355.65766\" xlink:href=\"#mc1fc8c99ed\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_16\">\n",
" <!-- 1111 -->\n",
" <g transform=\"translate(358.417035 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_17\">\n",
" <!-- Qubit State -->\n",
" <g transform=\"translate(182.728906 268.688437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 39.40625 66.21875 \n",
"Q 28.65625 66.21875 22.328125 58.203125 \n",
"Q 16.015625 50.203125 16.015625 36.375 \n",
"Q 16.015625 22.609375 22.328125 14.59375 \n",
"Q 28.65625 6.59375 39.40625 6.59375 \n",
"Q 50.140625 6.59375 56.421875 14.59375 \n",
"Q 62.703125 22.609375 62.703125 36.375 \n",
"Q 62.703125 50.203125 56.421875 58.203125 \n",
"Q 50.140625 66.21875 39.40625 66.21875 \n",
"z\n",
"M 53.21875 1.3125 \n",
"L 66.21875 -12.890625 \n",
"L 54.296875 -12.890625 \n",
"L 43.5 -1.21875 \n",
"Q 41.890625 -1.3125 41.03125 -1.359375 \n",
"Q 40.1875 -1.421875 39.40625 -1.421875 \n",
"Q 24.03125 -1.421875 14.8125 8.859375 \n",
"Q 5.609375 19.140625 5.609375 36.375 \n",
"Q 5.609375 53.65625 14.8125 63.9375 \n",
"Q 24.03125 74.21875 39.40625 74.21875 \n",
"Q 54.734375 74.21875 63.90625 63.9375 \n",
"Q 73.09375 53.65625 73.09375 36.375 \n",
"Q 73.09375 23.6875 67.984375 14.640625 \n",
"Q 62.890625 5.609375 53.21875 1.3125 \n",
"z\n",
"\" id=\"DejaVuSans-81\"/>\n",
" <path d=\"M 8.5 21.578125 \n",
"L 8.5 54.6875 \n",
"L 17.484375 54.6875 \n",
"L 17.484375 21.921875 \n",
"Q 17.484375 14.15625 20.5 10.265625 \n",
"Q 23.53125 6.390625 29.59375 6.390625 \n",
"Q 36.859375 6.390625 41.078125 11.03125 \n",
"Q 45.3125 15.671875 45.3125 23.6875 \n",
"L 45.3125 54.6875 \n",
"L 54.296875 54.6875 \n",
"L 54.296875 0 \n",
"L 45.3125 0 \n",
"L 45.3125 8.40625 \n",
"Q 42.046875 3.421875 37.71875 1 \n",
"Q 33.40625 -1.421875 27.6875 -1.421875 \n",
"Q 18.265625 -1.421875 13.375 4.4375 \n",
"Q 8.5 10.296875 8.5 21.578125 \n",
"z\n",
"M 31.109375 56 \n",
"z\n",
"\" id=\"DejaVuSans-117\"/>\n",
" <path d=\"M 48.6875 27.296875 \n",
"Q 48.6875 37.203125 44.609375 42.84375 \n",
"Q 40.53125 48.484375 33.40625 48.484375 \n",
"Q 26.265625 48.484375 22.1875 42.84375 \n",
"Q 18.109375 37.203125 18.109375 27.296875 \n",
"Q 18.109375 17.390625 22.1875 11.75 \n",
"Q 26.265625 6.109375 33.40625 6.109375 \n",
"Q 40.53125 6.109375 44.609375 11.75 \n",
"Q 48.6875 17.390625 48.6875 27.296875 \n",
"z\n",
"M 18.109375 46.390625 \n",
"Q 20.953125 51.265625 25.265625 53.625 \n",
"Q 29.59375 56 35.59375 56 \n",
"Q 45.5625 56 51.78125 48.09375 \n",
"Q 58.015625 40.1875 58.015625 27.296875 \n",
"Q 58.015625 14.40625 51.78125 6.484375 \n",
"Q 45.5625 -1.421875 35.59375 -1.421875 \n",
"Q 29.59375 -1.421875 25.265625 0.953125 \n",
"Q 20.953125 3.328125 18.109375 8.203125 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 75.984375 \n",
"L 18.109375 75.984375 \n",
"z\n",
"\" id=\"DejaVuSans-98\"/>\n",
" <path d=\"M 9.421875 54.6875 \n",
"L 18.40625 54.6875 \n",
"L 18.40625 0 \n",
"L 9.421875 0 \n",
"z\n",
"M 9.421875 75.984375 \n",
"L 18.40625 75.984375 \n",
"L 18.40625 64.59375 \n",
"L 9.421875 64.59375 \n",
"z\n",
"\" id=\"DejaVuSans-105\"/>\n",
" <path d=\"M 18.3125 70.21875 \n",
"L 18.3125 54.6875 \n",
"L 36.8125 54.6875 \n",
"L 36.8125 47.703125 \n",
"L 18.3125 47.703125 \n",
"L 18.3125 18.015625 \n",
"Q 18.3125 11.328125 20.140625 9.421875 \n",
"Q 21.96875 7.515625 27.59375 7.515625 \n",
"L 36.8125 7.515625 \n",
"L 36.8125 0 \n",
"L 27.59375 0 \n",
"Q 17.1875 0 13.234375 3.875 \n",
"Q 9.28125 7.765625 9.28125 18.015625 \n",
"L 9.28125 47.703125 \n",
"L 2.6875 47.703125 \n",
"L 2.6875 54.6875 \n",
"L 9.28125 54.6875 \n",
"L 9.28125 70.21875 \n",
"z\n",
"\" id=\"DejaVuSans-116\"/>\n",
" <path id=\"DejaVuSans-32\"/>\n",
" <path d=\"M 53.515625 70.515625 \n",
"L 53.515625 60.890625 \n",
"Q 47.90625 63.578125 42.921875 64.890625 \n",
"Q 37.9375 66.21875 33.296875 66.21875 \n",
"Q 25.25 66.21875 20.875 63.09375 \n",
"Q 16.5 59.96875 16.5 54.203125 \n",
"Q 16.5 49.359375 19.40625 46.890625 \n",
"Q 22.3125 44.4375 30.421875 42.921875 \n",
"L 36.375 41.703125 \n",
"Q 47.40625 39.59375 52.65625 34.296875 \n",
"Q 57.90625 29 57.90625 20.125 \n",
"Q 57.90625 9.515625 50.796875 4.046875 \n",
"Q 43.703125 -1.421875 29.984375 -1.421875 \n",
"Q 24.8125 -1.421875 18.96875 -0.25 \n",
"Q 13.140625 0.921875 6.890625 3.21875 \n",
"L 6.890625 13.375 \n",
"Q 12.890625 10.015625 18.65625 8.296875 \n",
"Q 24.421875 6.59375 29.984375 6.59375 \n",
"Q 38.421875 6.59375 43.015625 9.90625 \n",
"Q 47.609375 13.234375 47.609375 19.390625 \n",
"Q 47.609375 24.75 44.3125 27.78125 \n",
"Q 41.015625 30.8125 33.5 32.328125 \n",
"L 27.484375 33.5 \n",
"Q 16.453125 35.6875 11.515625 40.375 \n",
"Q 6.59375 45.0625 6.59375 53.421875 \n",
"Q 6.59375 63.09375 13.40625 68.65625 \n",
"Q 20.21875 74.21875 32.171875 74.21875 \n",
"Q 37.3125 74.21875 42.625 73.28125 \n",
"Q 47.953125 72.359375 53.515625 70.515625 \n",
"z\n",
"\" id=\"DejaVuSans-83\"/>\n",
" <path d=\"M 34.28125 27.484375 \n",
"Q 23.390625 27.484375 19.1875 25 \n",
"Q 14.984375 22.515625 14.984375 16.5 \n",
"Q 14.984375 11.71875 18.140625 8.90625 \n",
"Q 21.296875 6.109375 26.703125 6.109375 \n",
"Q 34.1875 6.109375 38.703125 11.40625 \n",
"Q 43.21875 16.703125 43.21875 25.484375 \n",
"L 43.21875 27.484375 \n",
"z\n",
"M 52.203125 31.203125 \n",
"L 52.203125 0 \n",
"L 43.21875 0 \n",
"L 43.21875 8.296875 \n",
"Q 40.140625 3.328125 35.546875 0.953125 \n",
"Q 30.953125 -1.421875 24.3125 -1.421875 \n",
"Q 15.921875 -1.421875 10.953125 3.296875 \n",
"Q 6 8.015625 6 15.921875 \n",
"Q 6 25.140625 12.171875 29.828125 \n",
"Q 18.359375 34.515625 30.609375 34.515625 \n",
"L 43.21875 34.515625 \n",
"L 43.21875 35.40625 \n",
"Q 43.21875 41.609375 39.140625 45 \n",
"Q 35.0625 48.390625 27.6875 48.390625 \n",
"Q 23 48.390625 18.546875 47.265625 \n",
"Q 14.109375 46.140625 10.015625 43.890625 \n",
"L 10.015625 52.203125 \n",
"Q 14.9375 54.109375 19.578125 55.046875 \n",
"Q 24.21875 56 28.609375 56 \n",
"Q 40.484375 56 46.34375 49.84375 \n",
"Q 52.203125 43.703125 52.203125 31.203125 \n",
"z\n",
"\" id=\"DejaVuSans-97\"/>\n",
" <path d=\"M 56.203125 29.59375 \n",
"L 56.203125 25.203125 \n",
"L 14.890625 25.203125 \n",
"Q 15.484375 15.921875 20.484375 11.0625 \n",
"Q 25.484375 6.203125 34.421875 6.203125 \n",
"Q 39.59375 6.203125 44.453125 7.46875 \n",
"Q 49.3125 8.734375 54.109375 11.28125 \n",
"L 54.109375 2.78125 \n",
"Q 49.265625 0.734375 44.1875 -0.34375 \n",
"Q 39.109375 -1.421875 33.890625 -1.421875 \n",
"Q 20.796875 -1.421875 13.15625 6.1875 \n",
"Q 5.515625 13.8125 5.515625 26.8125 \n",
"Q 5.515625 40.234375 12.765625 48.109375 \n",
"Q 20.015625 56 32.328125 56 \n",
"Q 43.359375 56 49.78125 48.890625 \n",
"Q 56.203125 41.796875 56.203125 29.59375 \n",
"z\n",
"M 47.21875 32.234375 \n",
"Q 47.125 39.59375 43.09375 43.984375 \n",
"Q 39.0625 48.390625 32.421875 48.390625 \n",
"Q 24.90625 48.390625 20.390625 44.140625 \n",
"Q 15.875 39.890625 15.1875 32.171875 \n",
"z\n",
"\" id=\"DejaVuSans-101\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-81\"/>\n",
" <use x=\"78.710938\" xlink:href=\"#DejaVuSans-117\"/>\n",
" <use x=\"142.089844\" xlink:href=\"#DejaVuSans-98\"/>\n",
" <use x=\"205.566406\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"233.349609\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"272.558594\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"304.345703\" xlink:href=\"#DejaVuSans-83\"/>\n",
" <use x=\"367.822266\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"407.03125\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"468.310547\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"507.519531\" xlink:href=\"#DejaVuSans-101\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"matplotlib.axis_2\">\n",
" <g id=\"ytick_1\">\n",
" <g id=\"line2d_17\">\n",
" <defs>\n",
" <path d=\"M 0 0 \n",
"L -3.5 0 \n",
"\" id=\"m8c08098b29\" style=\"stroke:#000000;stroke-width:0.8;\"/>\n",
" </defs>\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m8c08098b29\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_18\">\n",
" <!-- 0.0 -->\n",
" <g transform=\"translate(20.878125 228.439219)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 10.6875 12.40625 \n",
"L 21 12.40625 \n",
"L 21 0 \n",
"L 10.6875 0 \n",
"z\n",
"\" id=\"DejaVuSans-46\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_2\">\n",
" <g id=\"line2d_18\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m8c08098b29\" y=\"183.938316\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_19\">\n",
" <!-- 0.1 -->\n",
" <g transform=\"translate(20.878125 187.737535)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_3\">\n",
" <g id=\"line2d_19\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m8c08098b29\" y=\"143.236633\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_20\">\n",
" <!-- 0.2 -->\n",
" <g transform=\"translate(20.878125 147.035852)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 19.1875 8.296875 \n",
"L 53.609375 8.296875 \n",
"L 53.609375 0 \n",
"L 7.328125 0 \n",
"L 7.328125 8.296875 \n",
"Q 12.9375 14.109375 22.625 23.890625 \n",
"Q 32.328125 33.6875 34.8125 36.53125 \n",
"Q 39.546875 41.84375 41.421875 45.53125 \n",
"Q 43.3125 49.21875 43.3125 52.78125 \n",
"Q 43.3125 58.59375 39.234375 62.25 \n",
"Q 35.15625 65.921875 28.609375 65.921875 \n",
"Q 23.96875 65.921875 18.8125 64.3125 \n",
"Q 13.671875 62.703125 7.8125 59.421875 \n",
"L 7.8125 69.390625 \n",
"Q 13.765625 71.78125 18.9375 73 \n",
"Q 24.125 74.21875 28.421875 74.21875 \n",
"Q 39.75 74.21875 46.484375 68.546875 \n",
"Q 53.21875 62.890625 53.21875 53.421875 \n",
"Q 53.21875 48.921875 51.53125 44.890625 \n",
"Q 49.859375 40.875 45.40625 35.40625 \n",
"Q 44.1875 33.984375 37.640625 27.21875 \n",
"Q 31.109375 20.453125 19.1875 8.296875 \n",
"z\n",
"\" id=\"DejaVuSans-50\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-50\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_4\">\n",
" <g id=\"line2d_20\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m8c08098b29\" y=\"102.534949\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_21\">\n",
" <!-- 0.3 -->\n",
" <g transform=\"translate(20.878125 106.334168)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 40.578125 39.3125 \n",
"Q 47.65625 37.796875 51.625 33 \n",
"Q 55.609375 28.21875 55.609375 21.1875 \n",
"Q 55.609375 10.40625 48.1875 4.484375 \n",
"Q 40.765625 -1.421875 27.09375 -1.421875 \n",
"Q 22.515625 -1.421875 17.65625 -0.515625 \n",
"Q 12.796875 0.390625 7.625 2.203125 \n",
"L 7.625 11.71875 \n",
"Q 11.71875 9.328125 16.59375 8.109375 \n",
"Q 21.484375 6.890625 26.8125 6.890625 \n",
"Q 36.078125 6.890625 40.9375 10.546875 \n",
"Q 45.796875 14.203125 45.796875 21.1875 \n",
"Q 45.796875 27.640625 41.28125 31.265625 \n",
"Q 36.765625 34.90625 28.71875 34.90625 \n",
"L 20.21875 34.90625 \n",
"L 20.21875 43.015625 \n",
"L 29.109375 43.015625 \n",
"Q 36.375 43.015625 40.234375 45.921875 \n",
"Q 44.09375 48.828125 44.09375 54.296875 \n",
"Q 44.09375 59.90625 40.109375 62.90625 \n",
"Q 36.140625 65.921875 28.71875 65.921875 \n",
"Q 24.65625 65.921875 20.015625 65.03125 \n",
"Q 15.375 64.15625 9.8125 62.3125 \n",
"L 9.8125 71.09375 \n",
"Q 15.4375 72.65625 20.34375 73.4375 \n",
"Q 25.25 74.21875 29.59375 74.21875 \n",
"Q 40.828125 74.21875 47.359375 69.109375 \n",
"Q 53.90625 64.015625 53.90625 55.328125 \n",
"Q 53.90625 49.265625 50.4375 45.09375 \n",
"Q 46.96875 40.921875 40.578125 39.3125 \n",
"z\n",
"\" id=\"DejaVuSans-51\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-51\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_5\">\n",
" <g id=\"line2d_21\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m8c08098b29\" y=\"61.833266\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_22\">\n",
" <!-- 0.4 -->\n",
" <g transform=\"translate(20.878125 65.632484)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 37.796875 64.3125 \n",
"L 12.890625 25.390625 \n",
"L 37.796875 25.390625 \n",
"z\n",
"M 35.203125 72.90625 \n",
"L 47.609375 72.90625 \n",
"L 47.609375 25.390625 \n",
"L 58.015625 25.390625 \n",
"L 58.015625 17.1875 \n",
"L 47.609375 17.1875 \n",
"L 47.609375 0 \n",
"L 37.796875 0 \n",
"L 37.796875 17.1875 \n",
"L 4.890625 17.1875 \n",
"L 4.890625 26.703125 \n",
"z\n",
"\" id=\"DejaVuSans-52\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-52\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_6\">\n",
" <g id=\"line2d_22\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m8c08098b29\" y=\"21.131582\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_23\">\n",
" <!-- 0.5 -->\n",
" <g transform=\"translate(20.878125 24.930801)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 10.796875 72.90625 \n",
"L 49.515625 72.90625 \n",
"L 49.515625 64.59375 \n",
"L 19.828125 64.59375 \n",
"L 19.828125 46.734375 \n",
"Q 21.96875 47.46875 24.109375 47.828125 \n",
"Q 26.265625 48.1875 28.421875 48.1875 \n",
"Q 40.625 48.1875 47.75 41.5 \n",
"Q 54.890625 34.8125 54.890625 23.390625 \n",
"Q 54.890625 11.625 47.5625 5.09375 \n",
"Q 40.234375 -1.421875 26.90625 -1.421875 \n",
"Q 22.3125 -1.421875 17.546875 -0.640625 \n",
"Q 12.796875 0.140625 7.71875 1.703125 \n",
"L 7.71875 11.625 \n",
"Q 12.109375 9.234375 16.796875 8.0625 \n",
"Q 21.484375 6.890625 26.703125 6.890625 \n",
"Q 35.15625 6.890625 40.078125 11.328125 \n",
"Q 45.015625 15.765625 45.015625 23.390625 \n",
"Q 45.015625 31 40.078125 35.4375 \n",
"Q 35.15625 39.890625 26.703125 39.890625 \n",
"Q 22.75 39.890625 18.8125 39.015625 \n",
"Q 14.890625 38.140625 10.796875 36.28125 \n",
"z\n",
"\" id=\"DejaVuSans-53\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-53\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_24\">\n",
" <!-- Measured Probabilities -->\n",
" <g transform=\"translate(14.798438 172.470781)rotate(-90)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 9.8125 72.90625 \n",
"L 24.515625 72.90625 \n",
"L 43.109375 23.296875 \n",
"L 61.8125 72.90625 \n",
"L 76.515625 72.90625 \n",
"L 76.515625 0 \n",
"L 66.890625 0 \n",
"L 66.890625 64.015625 \n",
"L 48.09375 14.015625 \n",
"L 38.1875 14.015625 \n",
"L 19.390625 64.015625 \n",
"L 19.390625 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-77\"/>\n",
" <path d=\"M 44.28125 53.078125 \n",
"L 44.28125 44.578125 \n",
"Q 40.484375 46.53125 36.375 47.5 \n",
"Q 32.28125 48.484375 27.875 48.484375 \n",
"Q 21.1875 48.484375 17.84375 46.4375 \n",
"Q 14.5 44.390625 14.5 40.28125 \n",
"Q 14.5 37.15625 16.890625 35.375 \n",
"Q 19.28125 33.59375 26.515625 31.984375 \n",
"L 29.59375 31.296875 \n",
"Q 39.15625 29.25 43.1875 25.515625 \n",
"Q 47.21875 21.78125 47.21875 15.09375 \n",
"Q 47.21875 7.46875 41.1875 3.015625 \n",
"Q 35.15625 -1.421875 24.609375 -1.421875 \n",
"Q 20.21875 -1.421875 15.453125 -0.5625 \n",
"Q 10.6875 0.296875 5.421875 2 \n",
"L 5.421875 11.28125 \n",
"Q 10.40625 8.6875 15.234375 7.390625 \n",
"Q 20.0625 6.109375 24.8125 6.109375 \n",
"Q 31.15625 6.109375 34.5625 8.28125 \n",
"Q 37.984375 10.453125 37.984375 14.40625 \n",
"Q 37.984375 18.0625 35.515625 20.015625 \n",
"Q 33.0625 21.96875 24.703125 23.78125 \n",
"L 21.578125 24.515625 \n",
"Q 13.234375 26.265625 9.515625 29.90625 \n",
"Q 5.8125 33.546875 5.8125 39.890625 \n",
"Q 5.8125 47.609375 11.28125 51.796875 \n",
"Q 16.75 56 26.8125 56 \n",
"Q 31.78125 56 36.171875 55.265625 \n",
"Q 40.578125 54.546875 44.28125 53.078125 \n",
"z\n",
"\" id=\"DejaVuSans-115\"/>\n",
" <path d=\"M 41.109375 46.296875 \n",
"Q 39.59375 47.171875 37.8125 47.578125 \n",
"Q 36.03125 48 33.890625 48 \n",
"Q 26.265625 48 22.1875 43.046875 \n",
"Q 18.109375 38.09375 18.109375 28.8125 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 54.6875 \n",
"L 18.109375 54.6875 \n",
"L 18.109375 46.1875 \n",
"Q 20.953125 51.171875 25.484375 53.578125 \n",
"Q 30.03125 56 36.53125 56 \n",
"Q 37.453125 56 38.578125 55.875 \n",
"Q 39.703125 55.765625 41.0625 55.515625 \n",
"z\n",
"\" id=\"DejaVuSans-114\"/>\n",
" <path d=\"M 45.40625 46.390625 \n",
"L 45.40625 75.984375 \n",
"L 54.390625 75.984375 \n",
"L 54.390625 0 \n",
"L 45.40625 0 \n",
"L 45.40625 8.203125 \n",
"Q 42.578125 3.328125 38.25 0.953125 \n",
"Q 33.9375 -1.421875 27.875 -1.421875 \n",
"Q 17.96875 -1.421875 11.734375 6.484375 \n",
"Q 5.515625 14.40625 5.515625 27.296875 \n",
"Q 5.515625 40.1875 11.734375 48.09375 \n",
"Q 17.96875 56 27.875 56 \n",
"Q 33.9375 56 38.25 53.625 \n",
"Q 42.578125 51.265625 45.40625 46.390625 \n",
"z\n",
"M 14.796875 27.296875 \n",
"Q 14.796875 17.390625 18.875 11.75 \n",
"Q 22.953125 6.109375 30.078125 6.109375 \n",
"Q 37.203125 6.109375 41.296875 11.75 \n",
"Q 45.40625 17.390625 45.40625 27.296875 \n",
"Q 45.40625 37.203125 41.296875 42.84375 \n",
"Q 37.203125 48.484375 30.078125 48.484375 \n",
"Q 22.953125 48.484375 18.875 42.84375 \n",
"Q 14.796875 37.203125 14.796875 27.296875 \n",
"z\n",
"\" id=\"DejaVuSans-100\"/>\n",
" <path d=\"M 19.671875 64.796875 \n",
"L 19.671875 37.40625 \n",
"L 32.078125 37.40625 \n",
"Q 38.96875 37.40625 42.71875 40.96875 \n",
"Q 46.484375 44.53125 46.484375 51.125 \n",
"Q 46.484375 57.671875 42.71875 61.234375 \n",
"Q 38.96875 64.796875 32.078125 64.796875 \n",
"z\n",
"M 9.8125 72.90625 \n",
"L 32.078125 72.90625 \n",
"Q 44.34375 72.90625 50.609375 67.359375 \n",
"Q 56.890625 61.8125 56.890625 51.125 \n",
"Q 56.890625 40.328125 50.609375 34.8125 \n",
"Q 44.34375 29.296875 32.078125 29.296875 \n",
"L 19.671875 29.296875 \n",
"L 19.671875 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-80\"/>\n",
" <path d=\"M 30.609375 48.390625 \n",
"Q 23.390625 48.390625 19.1875 42.75 \n",
"Q 14.984375 37.109375 14.984375 27.296875 \n",
"Q 14.984375 17.484375 19.15625 11.84375 \n",
"Q 23.34375 6.203125 30.609375 6.203125 \n",
"Q 37.796875 6.203125 41.984375 11.859375 \n",
"Q 46.1875 17.53125 46.1875 27.296875 \n",
"Q 46.1875 37.015625 41.984375 42.703125 \n",
"Q 37.796875 48.390625 30.609375 48.390625 \n",
"z\n",
"M 30.609375 56 \n",
"Q 42.328125 56 49.015625 48.375 \n",
"Q 55.71875 40.765625 55.71875 27.296875 \n",
"Q 55.71875 13.875 49.015625 6.21875 \n",
"Q 42.328125 -1.421875 30.609375 -1.421875 \n",
"Q 18.84375 -1.421875 12.171875 6.21875 \n",
"Q 5.515625 13.875 5.515625 27.296875 \n",
"Q 5.515625 40.765625 12.171875 48.375 \n",
"Q 18.84375 56 30.609375 56 \n",
"z\n",
"\" id=\"DejaVuSans-111\"/>\n",
" <path d=\"M 9.421875 75.984375 \n",
"L 18.40625 75.984375 \n",
"L 18.40625 0 \n",
"L 9.421875 0 \n",
"z\n",
"\" id=\"DejaVuSans-108\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-77\"/>\n",
" <use x=\"86.279297\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"147.802734\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"209.082031\" xlink:href=\"#DejaVuSans-115\"/>\n",
" <use x=\"261.181641\" xlink:href=\"#DejaVuSans-117\"/>\n",
" <use x=\"324.560547\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"363.423828\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"424.947266\" xlink:href=\"#DejaVuSans-100\"/>\n",
" <use x=\"488.423828\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"520.210938\" xlink:href=\"#DejaVuSans-80\"/>\n",
" <use x=\"578.763672\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"617.626953\" xlink:href=\"#DejaVuSans-111\"/>\n",
" <use x=\"678.808594\" xlink:href=\"#DejaVuSans-98\"/>\n",
" <use x=\"742.285156\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"803.564453\" xlink:href=\"#DejaVuSans-98\"/>\n",
" <use x=\"867.041016\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"894.824219\" xlink:href=\"#DejaVuSans-108\"/>\n",
" <use x=\"922.607422\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"950.390625\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"989.599609\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"1017.382812\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"1078.90625\" xlink:href=\"#DejaVuSans-115\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"patch_19\">\n",
" <path d=\"M 43.78125 224.64 \n",
"L 43.78125 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_20\">\n",
" <path d=\"M 378.58125 224.64 \n",
"L 378.58125 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_21\">\n",
" <path d=\"M 43.78125 224.64 \n",
"L 378.58125 224.64 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_22\">\n",
" <path d=\"M 43.78125 7.2 \n",
"L 378.58125 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <defs>\n",
" <clipPath id=\"p5520171445\">\n",
" <rect height=\"217.44\" width=\"334.8\" x=\"43.78125\" y=\"7.2\"/>\n",
" </clipPath>\n",
" </defs>\n",
"</svg>\n"
],
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -2050,9 +778,8 @@ ...@@ -2050,9 +778,8 @@
} }
], ],
"source": [ "source": [
"with fluid.dygraph.guard():\n", "# 模拟重复测量电路输出态 1024 次\n",
" # 模拟重复测量电路输出态 1024 次\n", "prob_measure = cir.measure(plot=True)"
" prob_measure = cir.measure(plot=True)"
] ]
}, },
{ {
...@@ -2072,8 +799,8 @@ ...@@ -2072,8 +799,8 @@
"execution_count": 10, "execution_count": 10,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:04:50.540864Z", "end_time": "2021-02-22T11:11:34.819301Z",
"start_time": "2021-01-09T07:04:50.399744Z" "start_time": "2021-02-22T11:11:34.761119Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -2086,216 +813,7 @@ ...@@ -2086,216 +813,7 @@
}, },
{ {
"data": { "data": {
"image/svg+xml": [ "image/png": "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\n",
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Created with matplotlib (https://matplotlib.org/) -->\n",
"<svg height=\"302.4pt\" version=\"1.1\" viewBox=\"0 0 446.4 302.4\" width=\"446.4pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
" <metadata>\n",
" <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
" <cc:Work>\n",
" <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
" <dc:date>2021-01-09T15:04:50.508349</dc:date>\n",
" <dc:format>image/svg+xml</dc:format>\n",
" <dc:creator>\n",
" <cc:Agent>\n",
" <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\n",
" </cc:Agent>\n",
" </dc:creator>\n",
" </cc:Work>\n",
" </rdf:RDF>\n",
" </metadata>\n",
" <defs>\n",
" <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n",
" </defs>\n",
" <g id=\"figure_1\">\n",
" <g id=\"patch_1\">\n",
" <path d=\"M 0 302.4 \n",
"L 446.4 302.4 \n",
"L 446.4 0 \n",
"L 0 0 \n",
"z\n",
"\" style=\"fill:#ffffff;\"/>\n",
" </g>\n",
" <g id=\"axes_1\">\n",
" <g id=\"LineCollection_1\">\n",
" <path clip-path=\"url(#p51cca9015d)\" d=\"M 377.485714 151.2 \n",
"L 223.199993 48.342857 \n",
"\" style=\"fill:none;stroke:#000000;stroke-dasharray:7.4,3.2;stroke-dashoffset:0;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#p51cca9015d)\" d=\"M 377.485714 151.2 \n",
"L 223.200002 254.057143 \n",
"\" style=\"fill:none;stroke:#000000;stroke-dasharray:7.4,3.2;stroke-dashoffset:0;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#p51cca9015d)\" d=\"M 223.199993 48.342857 \n",
"L 68.914286 151.200009 \n",
"\" style=\"fill:none;stroke:#000000;stroke-dasharray:7.4,3.2;stroke-dashoffset:0;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#p51cca9015d)\" d=\"M 68.914286 151.200009 \n",
"L 223.200002 254.057143 \n",
"\" style=\"fill:none;stroke:#000000;stroke-dasharray:7.4,3.2;stroke-dashoffset:0;stroke-width:2;\"/>\n",
" </g>\n",
" <g id=\"PathCollection_1\">\n",
" <defs>\n",
" <path d=\"M 0 22.36068 \n",
"C 5.930122 22.36068 11.618159 20.004617 15.811388 15.811388 \n",
"C 20.004617 11.618159 22.36068 5.930122 22.36068 -0 \n",
"C 22.36068 -5.930122 20.004617 -11.618159 15.811388 -15.811388 \n",
"C 11.618159 -20.004617 5.930122 -22.36068 0 -22.36068 \n",
"C -5.930122 -22.36068 -11.618159 -20.004617 -15.811388 -15.811388 \n",
"C -20.004617 -11.618159 -22.36068 -5.930122 -22.36068 0 \n",
"C -22.36068 5.930122 -20.004617 11.618159 -15.811388 15.811388 \n",
"C -11.618159 20.004617 -5.930122 22.36068 0 22.36068 \n",
"z\n",
"\" id=\"C0_0_370df0a5fc\"/>\n",
" </defs>\n",
" <g clip-path=\"url(#p51cca9015d)\">\n",
" <use style=\"fill:#ff0000;stroke:#ff0000;\" x=\"377.485714\" xlink:href=\"#C0_0_370df0a5fc\" y=\"151.2\"/>\n",
" </g>\n",
" <g clip-path=\"url(#p51cca9015d)\">\n",
" <use style=\"fill:#0000ff;stroke:#0000ff;\" x=\"223.199993\" xlink:href=\"#C0_0_370df0a5fc\" y=\"48.342857\"/>\n",
" </g>\n",
" <g clip-path=\"url(#p51cca9015d)\">\n",
" <use style=\"fill:#ff0000;stroke:#ff0000;\" x=\"68.914286\" xlink:href=\"#C0_0_370df0a5fc\" y=\"151.200009\"/>\n",
" </g>\n",
" <g clip-path=\"url(#p51cca9015d)\">\n",
" <use style=\"fill:#0000ff;stroke:#0000ff;\" x=\"223.200002\" xlink:href=\"#C0_0_370df0a5fc\" y=\"254.057143\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_1\">\n",
" <g clip-path=\"url(#p51cca9015d)\">\n",
" <!-- 0 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(370.527902 156.71875)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 46 36.53125 \n",
"Q 46 50.203125 43.4375 55.78125 \n",
"Q 40.875 61.375 34.8125 61.375 \n",
"Q 28.765625 61.375 26.171875 55.78125 \n",
"Q 23.578125 50.203125 23.578125 36.53125 \n",
"Q 23.578125 22.703125 26.171875 17.03125 \n",
"Q 28.765625 11.375 34.8125 11.375 \n",
"Q 40.828125 11.375 43.40625 17.03125 \n",
"Q 46 22.703125 46 36.53125 \n",
"z\n",
"M 64.796875 36.375 \n",
"Q 64.796875 18.265625 56.984375 8.421875 \n",
"Q 49.171875 -1.421875 34.8125 -1.421875 \n",
"Q 20.40625 -1.421875 12.59375 8.421875 \n",
"Q 4.78125 18.265625 4.78125 36.375 \n",
"Q 4.78125 54.546875 12.59375 64.375 \n",
"Q 20.40625 74.21875 34.8125 74.21875 \n",
"Q 49.171875 74.21875 56.984375 64.375 \n",
"Q 64.796875 54.546875 64.796875 36.375 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-48\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_2\">\n",
" <g clip-path=\"url(#p51cca9015d)\">\n",
" <!-- 1 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(216.242181 53.861607)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 11.71875 12.984375 \n",
"L 28.328125 12.984375 \n",
"L 28.328125 60.109375 \n",
"L 11.28125 56.59375 \n",
"L 11.28125 69.390625 \n",
"L 28.21875 72.90625 \n",
"L 46.09375 72.90625 \n",
"L 46.09375 12.984375 \n",
"L 62.703125 12.984375 \n",
"L 62.703125 0 \n",
"L 11.71875 0 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-49\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_3\">\n",
" <g clip-path=\"url(#p51cca9015d)\">\n",
" <!-- 2 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(61.956473 156.718759)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 28.8125 13.8125 \n",
"L 60.890625 13.8125 \n",
"L 60.890625 0 \n",
"L 7.90625 0 \n",
"L 7.90625 13.8125 \n",
"L 34.515625 37.3125 \n",
"Q 38.09375 40.53125 39.796875 43.609375 \n",
"Q 41.5 46.6875 41.5 50 \n",
"Q 41.5 55.125 38.0625 58.25 \n",
"Q 34.625 61.375 28.90625 61.375 \n",
"Q 24.515625 61.375 19.28125 59.5 \n",
"Q 14.0625 57.625 8.109375 53.90625 \n",
"L 8.109375 69.921875 \n",
"Q 14.453125 72.015625 20.65625 73.109375 \n",
"Q 26.859375 74.21875 32.8125 74.21875 \n",
"Q 45.90625 74.21875 53.15625 68.453125 \n",
"Q 60.40625 62.703125 60.40625 52.390625 \n",
"Q 60.40625 46.4375 57.328125 41.28125 \n",
"Q 54.25 36.140625 44.390625 27.484375 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-50\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-50\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_4\">\n",
" <g clip-path=\"url(#p51cca9015d)\">\n",
" <!-- 3 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(216.242189 259.575893)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 46.578125 39.3125 \n",
"Q 53.953125 37.40625 57.78125 32.6875 \n",
"Q 61.625 27.984375 61.625 20.703125 \n",
"Q 61.625 9.859375 53.3125 4.21875 \n",
"Q 45.015625 -1.421875 29.109375 -1.421875 \n",
"Q 23.484375 -1.421875 17.84375 -0.515625 \n",
"Q 12.203125 0.390625 6.6875 2.203125 \n",
"L 6.6875 16.703125 \n",
"Q 11.96875 14.0625 17.15625 12.71875 \n",
"Q 22.359375 11.375 27.390625 11.375 \n",
"Q 34.859375 11.375 38.84375 13.953125 \n",
"Q 42.828125 16.546875 42.828125 21.390625 \n",
"Q 42.828125 26.375 38.75 28.9375 \n",
"Q 34.671875 31.5 26.703125 31.5 \n",
"L 19.1875 31.5 \n",
"L 19.1875 43.609375 \n",
"L 27.09375 43.609375 \n",
"Q 34.1875 43.609375 37.640625 45.828125 \n",
"Q 41.109375 48.046875 41.109375 52.59375 \n",
"Q 41.109375 56.78125 37.734375 59.078125 \n",
"Q 34.375 61.375 28.21875 61.375 \n",
"Q 23.6875 61.375 19.046875 60.34375 \n",
"Q 14.40625 59.328125 9.8125 57.328125 \n",
"L 9.8125 71.09375 \n",
"Q 15.375 72.65625 20.84375 73.4375 \n",
"Q 26.3125 74.21875 31.59375 74.21875 \n",
"Q 45.796875 74.21875 52.84375 69.546875 \n",
"Q 59.90625 64.890625 59.90625 55.515625 \n",
"Q 59.90625 49.125 56.53125 45.046875 \n",
"Q 53.171875 40.96875 46.578125 39.3125 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-51\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-51\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <defs>\n",
" <clipPath id=\"p51cca9015d\">\n",
" <rect height=\"288\" width=\"432\" x=\"7.2\" y=\"7.2\"/>\n",
" </clipPath>\n",
" </defs>\n",
"</svg>\n"
],
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -2348,9 +866,7 @@ ...@@ -2348,9 +866,7 @@
"\n", "\n",
"[2] Farhi, E., Goldstone, J., Gutmann, S. & Sipser, M. Quantum computation by adiabatic evolution. [arXiv:quant-ph/0001106 (2000).](https://arxiv.org/abs/quant-ph/0001106)\n", "[2] Farhi, E., Goldstone, J., Gutmann, S. & Sipser, M. Quantum computation by adiabatic evolution. [arXiv:quant-ph/0001106 (2000).](https://arxiv.org/abs/quant-ph/0001106)\n",
"\n", "\n",
"[3] Duan, R. Quantum Adiabatic Theorem Revisited. [arXiv:2003.03063 (2020).](https://arxiv.org/abs/2003.03063)\n", "[3] Duan, R. Quantum Adiabatic Theorem Revisited. [arXiv:2003.03063 (2020).](https://arxiv.org/abs/2003.03063)"
"\n",
"\n"
] ]
} }
], ],
...@@ -2370,7 +886,7 @@ ...@@ -2370,7 +886,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.10" "version": "3.7.0"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
...@@ -2384,6 +900,35 @@ ...@@ -2384,6 +900,35 @@
"toc_position": {}, "toc_position": {},
"toc_section_display": true, "toc_section_display": true,
"toc_window_display": true "toc_window_display": true
},
"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
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -357,21 +357,21 @@ ...@@ -357,21 +357,21 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:54:37.202331Z", "end_time": "2021-03-09T06:10:24.136791Z",
"start_time": "2021-01-09T06:54:32.649071Z" "start_time": "2021-03-09T06:10:19.007907Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"# Import related modules from Paddle Quantum and PaddlePaddle\n", "# Import related modules from Paddle Quantum and PaddlePaddle\n",
"from paddle import fluid\n", "import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import pauli_str_to_matrix\n", "from paddle_quantum.utils import pauli_str_to_matrix\n",
"\n", "\n",
"# Import additional packages needed\n", "# Import additional packages needed\n",
"import numpy as np\n", "import numpy as np\n",
"from numpy import pi as PI\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"%config InlineBackend.figure_format = 'svg'\n",
"import networkx as nx" "import networkx as nx"
] ]
}, },
...@@ -387,217 +387,22 @@ ...@@ -387,217 +387,22 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:54:37.384183Z", "end_time": "2021-03-09T06:10:24.538191Z",
"start_time": "2021-01-09T06:54:37.204886Z" "start_time": "2021-03-09T06:10:24.142186Z"
} }
}, },
"outputs": [ "outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/v_yusizhuo/opt/anaconda3/envs/pq2.0.1/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n",
" and should_run_async(code)\n"
]
},
{ {
"data": { "data": {
"image/svg+xml": [ "image/png": "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\n",
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Created with matplotlib (https://matplotlib.org/) -->\n",
"<svg height=\"231.84pt\" version=\"1.1\" viewBox=\"0 0 349.2 231.84\" width=\"349.2pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
" <metadata>\n",
" <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
" <cc:Work>\n",
" <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
" <dc:date>2021-01-09T14:54:37.352699</dc:date>\n",
" <dc:format>image/svg+xml</dc:format>\n",
" <dc:creator>\n",
" <cc:Agent>\n",
" <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\n",
" </cc:Agent>\n",
" </dc:creator>\n",
" </cc:Work>\n",
" </rdf:RDF>\n",
" </metadata>\n",
" <defs>\n",
" <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n",
" </defs>\n",
" <g id=\"figure_1\">\n",
" <g id=\"patch_1\">\n",
" <path d=\"M 0 231.84 \n",
"L 349.2 231.84 \n",
"L 349.2 0 \n",
"L 0 0 \n",
"z\n",
"\" style=\"fill:none;\"/>\n",
" </g>\n",
" <g id=\"axes_1\">\n",
" <g id=\"LineCollection_1\">\n",
" <path clip-path=\"url(#p8c02f84376)\" d=\"M 294.171429 115.92 \n",
"L 174.599995 38.262857 \n",
"\" style=\"fill:none;stroke:#000000;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#p8c02f84376)\" d=\"M 294.171429 115.92 \n",
"L 174.600001 193.577143 \n",
"\" style=\"fill:none;stroke:#000000;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#p8c02f84376)\" d=\"M 174.599995 38.262857 \n",
"L 55.028571 115.920007 \n",
"\" style=\"fill:none;stroke:#000000;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#p8c02f84376)\" d=\"M 55.028571 115.920007 \n",
"L 174.600001 193.577143 \n",
"\" style=\"fill:none;stroke:#000000;stroke-width:2;\"/>\n",
" </g>\n",
" <g id=\"PathCollection_1\">\n",
" <defs>\n",
" <path d=\"M 0 22.36068 \n",
"C 5.930122 22.36068 11.618159 20.004617 15.811388 15.811388 \n",
"C 20.004617 11.618159 22.36068 5.930122 22.36068 0 \n",
"C 22.36068 -5.930122 20.004617 -11.618159 15.811388 -15.811388 \n",
"C 11.618159 -20.004617 5.930122 -22.36068 0 -22.36068 \n",
"C -5.930122 -22.36068 -11.618159 -20.004617 -15.811388 -15.811388 \n",
"C -20.004617 -11.618159 -22.36068 -5.930122 -22.36068 0 \n",
"C -22.36068 5.930122 -20.004617 11.618159 -15.811388 15.811388 \n",
"C -11.618159 20.004617 -5.930122 22.36068 0 22.36068 \n",
"z\n",
"\" id=\"mb1b023645b\" style=\"stroke:#1f78b4;\"/>\n",
" </defs>\n",
" <g clip-path=\"url(#p8c02f84376)\">\n",
" <use style=\"fill:#1f78b4;stroke:#1f78b4;\" x=\"294.171429\" xlink:href=\"#mb1b023645b\" y=\"115.92\"/>\n",
" <use style=\"fill:#1f78b4;stroke:#1f78b4;\" x=\"174.599995\" xlink:href=\"#mb1b023645b\" y=\"38.262857\"/>\n",
" <use style=\"fill:#1f78b4;stroke:#1f78b4;\" x=\"55.028571\" xlink:href=\"#mb1b023645b\" y=\"115.920007\"/>\n",
" <use style=\"fill:#1f78b4;stroke:#1f78b4;\" x=\"174.600001\" xlink:href=\"#mb1b023645b\" y=\"193.577143\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_1\">\n",
" <g clip-path=\"url(#p8c02f84376)\">\n",
" <!-- 0 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(287.213616 121.43875)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 46 36.53125 \n",
"Q 46 50.203125 43.4375 55.78125 \n",
"Q 40.875 61.375 34.8125 61.375 \n",
"Q 28.765625 61.375 26.171875 55.78125 \n",
"Q 23.578125 50.203125 23.578125 36.53125 \n",
"Q 23.578125 22.703125 26.171875 17.03125 \n",
"Q 28.765625 11.375 34.8125 11.375 \n",
"Q 40.828125 11.375 43.40625 17.03125 \n",
"Q 46 22.703125 46 36.53125 \n",
"z\n",
"M 64.796875 36.375 \n",
"Q 64.796875 18.265625 56.984375 8.421875 \n",
"Q 49.171875 -1.421875 34.8125 -1.421875 \n",
"Q 20.40625 -1.421875 12.59375 8.421875 \n",
"Q 4.78125 18.265625 4.78125 36.375 \n",
"Q 4.78125 54.546875 12.59375 64.375 \n",
"Q 20.40625 74.21875 34.8125 74.21875 \n",
"Q 49.171875 74.21875 56.984375 64.375 \n",
"Q 64.796875 54.546875 64.796875 36.375 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-48\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_2\">\n",
" <g clip-path=\"url(#p8c02f84376)\">\n",
" <!-- 1 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(167.642182 43.781607)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 11.71875 12.984375 \n",
"L 28.328125 12.984375 \n",
"L 28.328125 60.109375 \n",
"L 11.28125 56.59375 \n",
"L 11.28125 69.390625 \n",
"L 28.21875 72.90625 \n",
"L 46.09375 72.90625 \n",
"L 46.09375 12.984375 \n",
"L 62.703125 12.984375 \n",
"L 62.703125 0 \n",
"L 11.71875 0 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-49\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_3\">\n",
" <g clip-path=\"url(#p8c02f84376)\">\n",
" <!-- 2 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(48.070759 121.438757)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 28.8125 13.8125 \n",
"L 60.890625 13.8125 \n",
"L 60.890625 0 \n",
"L 7.90625 0 \n",
"L 7.90625 13.8125 \n",
"L 34.515625 37.3125 \n",
"Q 38.09375 40.53125 39.796875 43.609375 \n",
"Q 41.5 46.6875 41.5 50 \n",
"Q 41.5 55.125 38.0625 58.25 \n",
"Q 34.625 61.375 28.90625 61.375 \n",
"Q 24.515625 61.375 19.28125 59.5 \n",
"Q 14.0625 57.625 8.109375 53.90625 \n",
"L 8.109375 69.921875 \n",
"Q 14.453125 72.015625 20.65625 73.109375 \n",
"Q 26.859375 74.21875 32.8125 74.21875 \n",
"Q 45.90625 74.21875 53.15625 68.453125 \n",
"Q 60.40625 62.703125 60.40625 52.390625 \n",
"Q 60.40625 46.4375 57.328125 41.28125 \n",
"Q 54.25 36.140625 44.390625 27.484375 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-50\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-50\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_4\">\n",
" <g clip-path=\"url(#p8c02f84376)\">\n",
" <!-- 3 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(167.642189 199.095893)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 46.578125 39.3125 \n",
"Q 53.953125 37.40625 57.78125 32.6875 \n",
"Q 61.625 27.984375 61.625 20.703125 \n",
"Q 61.625 9.859375 53.3125 4.21875 \n",
"Q 45.015625 -1.421875 29.109375 -1.421875 \n",
"Q 23.484375 -1.421875 17.84375 -0.515625 \n",
"Q 12.203125 0.390625 6.6875 2.203125 \n",
"L 6.6875 16.703125 \n",
"Q 11.96875 14.0625 17.15625 12.71875 \n",
"Q 22.359375 11.375 27.390625 11.375 \n",
"Q 34.859375 11.375 38.84375 13.953125 \n",
"Q 42.828125 16.546875 42.828125 21.390625 \n",
"Q 42.828125 26.375 38.75 28.9375 \n",
"Q 34.671875 31.5 26.703125 31.5 \n",
"L 19.1875 31.5 \n",
"L 19.1875 43.609375 \n",
"L 27.09375 43.609375 \n",
"Q 34.1875 43.609375 37.640625 45.828125 \n",
"Q 41.109375 48.046875 41.109375 52.59375 \n",
"Q 41.109375 56.78125 37.734375 59.078125 \n",
"Q 34.375 61.375 28.21875 61.375 \n",
"Q 23.6875 61.375 19.046875 60.34375 \n",
"Q 14.40625 59.328125 9.8125 57.328125 \n",
"L 9.8125 71.09375 \n",
"Q 15.375 72.65625 20.84375 73.4375 \n",
"Q 26.3125 74.21875 31.59375 74.21875 \n",
"Q 45.796875 74.21875 52.84375 69.546875 \n",
"Q 59.90625 64.890625 59.90625 55.515625 \n",
"Q 59.90625 49.125 56.53125 45.046875 \n",
"Q 53.171875 40.96875 46.578125 39.3125 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-51\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-51\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <defs>\n",
" <clipPath id=\"p8c02f84376\">\n",
" <rect height=\"217.44\" width=\"334.8\" x=\"7.2\" y=\"7.2\"/>\n",
" </clipPath>\n",
" </defs>\n",
"</svg>\n"
],
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -645,8 +450,8 @@ ...@@ -645,8 +450,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:54:37.397513Z", "end_time": "2021-03-09T06:10:24.568875Z",
"start_time": "2021-01-09T06:54:37.390477Z" "start_time": "2021-03-09T06:10:24.555025Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -685,8 +490,8 @@ ...@@ -685,8 +490,8 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:54:37.412726Z", "end_time": "2021-03-09T06:10:24.589057Z",
"start_time": "2021-01-09T06:54:37.402304Z" "start_time": "2021-03-09T06:10:24.578446Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -743,8 +548,8 @@ ...@@ -743,8 +548,8 @@
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:54:37.438826Z", "end_time": "2021-03-09T06:10:24.716543Z",
"start_time": "2021-01-09T06:54:37.416589Z" "start_time": "2021-03-09T06:10:24.700063Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -802,24 +607,23 @@ ...@@ -802,24 +607,23 @@
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:54:39.039309Z", "end_time": "2021-03-09T06:10:26.069461Z",
"start_time": "2021-01-09T06:54:39.027860Z" "start_time": "2021-03-09T06:10:26.057685Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Net(fluid.dygraph.Layer):\n", "class Net(paddle.nn.Layer):\n",
" def __init__(\n", " def __init__(self, p, dtype=\"float64\",):\n",
" self,\n",
" p,\n",
" param_attr=fluid.initializer.Uniform(low=0.0, high=np.pi, seed=1024),\n",
" dtype=\"float64\",\n",
" ):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
"\n", "\n",
" self.p = p\n", " self.p = p\n",
" self.gamma = self.create_parameter(shape=[self.p], attr=param_attr, dtype=dtype, is_bias=False)\n", " self.gamma = self.create_parameter(shape=[self.p], \n",
" self.beta = self.create_parameter(shape=[self.p], attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI), \n",
" dtype=dtype, is_bias=False)\n",
" self.beta = self.create_parameter(shape=[self.p], \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI), \n",
" dtype=dtype, is_bias=False)\n",
"\n", "\n",
" def forward(self):\n", " def forward(self):\n",
" # Define QAOA's quantum circuit\n", " # Define QAOA's quantum circuit\n",
...@@ -846,22 +650,23 @@ ...@@ -846,22 +650,23 @@
"execution_count": 7, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:54:40.191271Z", "end_time": "2021-03-09T06:10:26.971045Z",
"start_time": "2021-01-09T06:54:40.187047Z" "start_time": "2021-03-09T06:10:26.961776Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"p = 4 # Number of layers in the quantum circuit\n", "p = 4 # Number of layers in the quantum circuit\n",
"ITR = 120 # Number of training iterations\n", "ITR = 120 # Number of training iterations\n",
"LR = 0.1 # Learning rate of the optimization method based on gradient descent" "LR = 0.1 # Learning rate of the optimization method based on gradient descent\n",
"SEED = 1024 # Set global RNG seed "
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Here, we optimize the network defined above in PaddlePaddle's dynamic graph." "Here, we optimize the network defined above in PaddlePaddle."
] ]
}, },
{ {
...@@ -869,8 +674,8 @@ ...@@ -869,8 +674,8 @@
"execution_count": 8, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:55:09.934656Z", "end_time": "2021-03-09T06:11:07.397318Z",
"start_time": "2021-01-09T06:54:41.756374Z" "start_time": "2021-03-09T06:10:27.928944Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -878,45 +683,46 @@ ...@@ -878,45 +683,46 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 10 loss: -3.7473\n", "iter: 10 loss: -3.8886\n",
"iter: 20 loss: -3.9696\n", "iter: 20 loss: -3.9134\n",
"iter: 30 loss: -3.9539\n", "iter: 30 loss: -3.9659\n",
"iter: 40 loss: -3.9710\n", "iter: 40 loss: -3.9906\n",
"iter: 50 loss: -3.9930\n", "iter: 50 loss: -3.9979\n",
"iter: 60 loss: -3.9991\n", "iter: 60 loss: -3.9993\n",
"iter: 70 loss: -3.9984\n", "iter: 70 loss: -3.9998\n",
"iter: 80 loss: -3.9998\n", "iter: 80 loss: -3.9999\n",
"iter: 90 loss: -3.9998\n", "iter: 90 loss: -4.0000\n",
"iter: 100 loss: -4.0000\n", "iter: 100 loss: -4.0000\n",
"iter: 110 loss: -4.0000\n", "iter: 110 loss: -4.0000\n",
"iter: 120 loss: -4.0000\n", "iter: 120 loss: -4.0000\n",
"Optimized parameters gamma:\n", "Optimized parameters gamma:\n",
" [0.70063329 0.45026914 1.17355432 2.13276803]\n", " [3.14046713 0.73681226 4.99897226 0.46481489]\n",
"Optimized parameters beta:\n", "Optimized parameters beta:\n",
" [-0.02466894 -0.20348931 1.12024105 0.61099467]\n" " [0.82379898 2.50618308 4.85422542 1.90024859]\n"
] ]
} }
], ],
"source": [ "source": [
"with fluid.dygraph.guard():\n", "paddle.seed(SEED)\n",
" net = Net(p)\n", "\n",
" # Use Adam optimizer\n", "net = Net(p)\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "# Use Adam optimizer\n",
" # Gradient descent iteration\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" for itr in range(1, ITR + 1):\n", "# Gradient descent iteration\n",
" # Run the network defined above\n", "for itr in range(1, ITR + 1):\n",
" loss, cir = net()\n", " # Run the network defined above\n",
" # Calculate the gradient and optimize\n", " loss, cir = net()\n",
" loss.backward()\n", " # Calculate the gradient and optimize\n",
" opt.minimize(loss)\n", " loss.backward()\n",
" net.clear_gradients()\n", " opt.minimize(loss)\n",
" if itr% 10 == 0:\n", " opt.clear_grad()\n",
" print(\"iter:\", itr, \"loss:\", \"%.4f\"% loss.numpy())\n", " if itr% 10 == 0:\n",
"\n", " print(\"iter:\", itr, \"loss:\", \"%.4f\"% loss.numpy())\n",
" gamma_opt = net.gamma.numpy()\n", "\n",
" print(\"Optimized parameters gamma:\\n\", gamma_opt)\n", "gamma_opt = net.gamma.numpy()\n",
" beta_opt = net.beta.numpy()\n", "print(\"Optimized parameters gamma:\\n\", gamma_opt)\n",
" print(\"Optimized parameters beta:\\n\", beta_opt)" "beta_opt = net.beta.numpy()\n",
"print(\"Optimized parameters beta:\\n\", beta_opt)"
] ]
}, },
{ {
...@@ -942,1094 +748,14 @@ ...@@ -942,1094 +748,14 @@
"execution_count": 9, "execution_count": 9,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:55:10.320339Z", "end_time": "2021-03-09T06:11:08.010481Z",
"start_time": "2021-01-09T06:55:09.938137Z" "start_time": "2021-03-09T06:11:07.444837Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/svg+xml": [ "image/png": "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\n",
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Created with matplotlib (https://matplotlib.org/) -->\n",
"<svg height=\"277.968125pt\" version=\"1.1\" viewBox=\"0 0 385.78125 277.968125\" width=\"385.78125pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
" <metadata>\n",
" <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
" <cc:Work>\n",
" <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
" <dc:date>2021-01-09T14:55:10.216565</dc:date>\n",
" <dc:format>image/svg+xml</dc:format>\n",
" <dc:creator>\n",
" <cc:Agent>\n",
" <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\n",
" </cc:Agent>\n",
" </dc:creator>\n",
" </cc:Work>\n",
" </rdf:RDF>\n",
" </metadata>\n",
" <defs>\n",
" <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n",
" </defs>\n",
" <g id=\"figure_1\">\n",
" <g id=\"patch_1\">\n",
" <path d=\"M 0 277.968125 \n",
"L 385.78125 277.968125 \n",
"L 385.78125 0 \n",
"L 0 0 \n",
"z\n",
"\" style=\"fill:none;\"/>\n",
" </g>\n",
" <g id=\"axes_1\">\n",
" <g id=\"patch_2\">\n",
" <path d=\"M 43.78125 224.64 \n",
"L 378.58125 224.64 \n",
"L 378.58125 7.2 \n",
"L 43.78125 7.2 \n",
"z\n",
"\" style=\"fill:#ffffff;\"/>\n",
" </g>\n",
" <g id=\"patch_3\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 58.999432 224.64 \n",
"L 74.410249 224.64 \n",
"L 74.410249 224.64 \n",
"L 58.999432 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_4\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 78.262953 224.64 \n",
"L 93.67377 224.64 \n",
"L 93.67377 224.64 \n",
"L 78.262953 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_5\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 97.526474 224.64 \n",
"L 112.937291 224.64 \n",
"L 112.937291 224.64 \n",
"L 97.526474 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_6\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 116.789996 224.64 \n",
"L 132.200813 224.64 \n",
"L 132.200813 224.64 \n",
"L 116.789996 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_7\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 136.053517 224.64 \n",
"L 151.464334 224.64 \n",
"L 151.464334 224.64 \n",
"L 136.053517 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_8\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 155.317038 224.64 \n",
"L 170.727855 224.64 \n",
"L 170.727855 27.039128 \n",
"L 155.317038 27.039128 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_9\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 174.58056 224.64 \n",
"L 189.991377 224.64 \n",
"L 189.991377 224.64 \n",
"L 174.58056 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_10\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 193.844081 224.64 \n",
"L 209.254898 224.64 \n",
"L 209.254898 224.64 \n",
"L 193.844081 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_11\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 213.107602 224.64 \n",
"L 228.518419 224.64 \n",
"L 228.518419 224.64 \n",
"L 213.107602 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_12\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 232.371123 224.64 \n",
"L 247.78194 224.64 \n",
"L 247.78194 224.64 \n",
"L 232.371123 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_13\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 251.634645 224.64 \n",
"L 267.045462 224.64 \n",
"L 267.045462 17.554286 \n",
"L 251.634645 17.554286 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_14\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 270.898166 224.64 \n",
"L 286.308983 224.64 \n",
"L 286.308983 224.64 \n",
"L 270.898166 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_15\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 290.161687 224.64 \n",
"L 305.572504 224.64 \n",
"L 305.572504 224.64 \n",
"L 290.161687 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_16\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 309.425209 224.64 \n",
"L 324.836026 224.64 \n",
"L 324.836026 224.64 \n",
"L 309.425209 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_17\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 328.68873 224.64 \n",
"L 344.099547 224.64 \n",
"L 344.099547 224.64 \n",
"L 328.68873 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"patch_18\">\n",
" <path clip-path=\"url(#p1913dbb0ed)\" d=\"M 347.952251 224.64 \n",
"L 363.363068 224.64 \n",
"L 363.363068 224.64 \n",
"L 347.952251 224.64 \n",
"z\n",
"\" style=\"fill:#1f77b4;\"/>\n",
" </g>\n",
" <g id=\"matplotlib.axis_1\">\n",
" <g id=\"xtick_1\">\n",
" <g id=\"line2d_1\">\n",
" <defs>\n",
" <path d=\"M 0 0 \n",
"L 0 3.5 \n",
"\" id=\"mb21437fbbb\" style=\"stroke:#000000;stroke-width:0.8;\"/>\n",
" </defs>\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"66.70484\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_1\">\n",
" <!-- 0000 -->\n",
" <g transform=\"translate(69.464215 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 31.78125 66.40625 \n",
"Q 24.171875 66.40625 20.328125 58.90625 \n",
"Q 16.5 51.421875 16.5 36.375 \n",
"Q 16.5 21.390625 20.328125 13.890625 \n",
"Q 24.171875 6.390625 31.78125 6.390625 \n",
"Q 39.453125 6.390625 43.28125 13.890625 \n",
"Q 47.125 21.390625 47.125 36.375 \n",
"Q 47.125 51.421875 43.28125 58.90625 \n",
"Q 39.453125 66.40625 31.78125 66.40625 \n",
"z\n",
"M 31.78125 74.21875 \n",
"Q 44.046875 74.21875 50.515625 64.515625 \n",
"Q 56.984375 54.828125 56.984375 36.375 \n",
"Q 56.984375 17.96875 50.515625 8.265625 \n",
"Q 44.046875 -1.421875 31.78125 -1.421875 \n",
"Q 19.53125 -1.421875 13.0625 8.265625 \n",
"Q 6.59375 17.96875 6.59375 36.375 \n",
"Q 6.59375 54.828125 13.0625 64.515625 \n",
"Q 19.53125 74.21875 31.78125 74.21875 \n",
"z\n",
"\" id=\"DejaVuSans-48\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_2\">\n",
" <g id=\"line2d_2\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"85.968362\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_2\">\n",
" <!-- 0001 -->\n",
" <g transform=\"translate(88.727737 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 12.40625 8.296875 \n",
"L 28.515625 8.296875 \n",
"L 28.515625 63.921875 \n",
"L 10.984375 60.40625 \n",
"L 10.984375 69.390625 \n",
"L 28.421875 72.90625 \n",
"L 38.28125 72.90625 \n",
"L 38.28125 8.296875 \n",
"L 54.390625 8.296875 \n",
"L 54.390625 0 \n",
"L 12.40625 0 \n",
"z\n",
"\" id=\"DejaVuSans-49\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_3\">\n",
" <g id=\"line2d_3\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"105.231883\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_3\">\n",
" <!-- 0010 -->\n",
" <g transform=\"translate(107.991258 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_4\">\n",
" <g id=\"line2d_4\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"124.495404\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_4\">\n",
" <!-- 0011 -->\n",
" <g transform=\"translate(127.254779 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_5\">\n",
" <g id=\"line2d_5\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"143.758925\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_5\">\n",
" <!-- 0100 -->\n",
" <g transform=\"translate(146.5183 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_6\">\n",
" <g id=\"line2d_6\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"163.022447\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_6\">\n",
" <!-- 0101 -->\n",
" <g transform=\"translate(165.781822 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_7\">\n",
" <g id=\"line2d_7\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"182.285968\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_7\">\n",
" <!-- 0110 -->\n",
" <g transform=\"translate(185.045343 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_8\">\n",
" <g id=\"line2d_8\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"201.549489\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_8\">\n",
" <!-- 0111 -->\n",
" <g transform=\"translate(204.308864 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_9\">\n",
" <g id=\"line2d_9\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"220.813011\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_9\">\n",
" <!-- 1000 -->\n",
" <g transform=\"translate(223.572386 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_10\">\n",
" <g id=\"line2d_10\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"240.076532\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_10\">\n",
" <!-- 1001 -->\n",
" <g transform=\"translate(242.835907 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_11\">\n",
" <g id=\"line2d_11\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"259.340053\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_11\">\n",
" <!-- 1010 -->\n",
" <g transform=\"translate(262.099428 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_12\">\n",
" <g id=\"line2d_12\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"278.603575\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_12\">\n",
" <!-- 1011 -->\n",
" <g transform=\"translate(281.36295 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_13\">\n",
" <g id=\"line2d_13\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"297.867096\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_13\">\n",
" <!-- 1100 -->\n",
" <g transform=\"translate(300.626471 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_14\">\n",
" <g id=\"line2d_14\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"317.130617\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_14\">\n",
" <!-- 1101 -->\n",
" <g transform=\"translate(319.889992 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_15\">\n",
" <g id=\"line2d_15\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"336.394138\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_15\">\n",
" <!-- 1110 -->\n",
" <g transform=\"translate(339.153513 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_16\">\n",
" <g id=\"line2d_16\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"355.65766\" xlink:href=\"#mb21437fbbb\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_16\">\n",
" <!-- 1111 -->\n",
" <g transform=\"translate(358.417035 257.09)rotate(-90)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"190.869141\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_17\">\n",
" <!-- Qubit State -->\n",
" <g transform=\"translate(182.728906 268.688437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 39.40625 66.21875 \n",
"Q 28.65625 66.21875 22.328125 58.203125 \n",
"Q 16.015625 50.203125 16.015625 36.375 \n",
"Q 16.015625 22.609375 22.328125 14.59375 \n",
"Q 28.65625 6.59375 39.40625 6.59375 \n",
"Q 50.140625 6.59375 56.421875 14.59375 \n",
"Q 62.703125 22.609375 62.703125 36.375 \n",
"Q 62.703125 50.203125 56.421875 58.203125 \n",
"Q 50.140625 66.21875 39.40625 66.21875 \n",
"z\n",
"M 53.21875 1.3125 \n",
"L 66.21875 -12.890625 \n",
"L 54.296875 -12.890625 \n",
"L 43.5 -1.21875 \n",
"Q 41.890625 -1.3125 41.03125 -1.359375 \n",
"Q 40.1875 -1.421875 39.40625 -1.421875 \n",
"Q 24.03125 -1.421875 14.8125 8.859375 \n",
"Q 5.609375 19.140625 5.609375 36.375 \n",
"Q 5.609375 53.65625 14.8125 63.9375 \n",
"Q 24.03125 74.21875 39.40625 74.21875 \n",
"Q 54.734375 74.21875 63.90625 63.9375 \n",
"Q 73.09375 53.65625 73.09375 36.375 \n",
"Q 73.09375 23.6875 67.984375 14.640625 \n",
"Q 62.890625 5.609375 53.21875 1.3125 \n",
"z\n",
"\" id=\"DejaVuSans-81\"/>\n",
" <path d=\"M 8.5 21.578125 \n",
"L 8.5 54.6875 \n",
"L 17.484375 54.6875 \n",
"L 17.484375 21.921875 \n",
"Q 17.484375 14.15625 20.5 10.265625 \n",
"Q 23.53125 6.390625 29.59375 6.390625 \n",
"Q 36.859375 6.390625 41.078125 11.03125 \n",
"Q 45.3125 15.671875 45.3125 23.6875 \n",
"L 45.3125 54.6875 \n",
"L 54.296875 54.6875 \n",
"L 54.296875 0 \n",
"L 45.3125 0 \n",
"L 45.3125 8.40625 \n",
"Q 42.046875 3.421875 37.71875 1 \n",
"Q 33.40625 -1.421875 27.6875 -1.421875 \n",
"Q 18.265625 -1.421875 13.375 4.4375 \n",
"Q 8.5 10.296875 8.5 21.578125 \n",
"z\n",
"M 31.109375 56 \n",
"z\n",
"\" id=\"DejaVuSans-117\"/>\n",
" <path d=\"M 48.6875 27.296875 \n",
"Q 48.6875 37.203125 44.609375 42.84375 \n",
"Q 40.53125 48.484375 33.40625 48.484375 \n",
"Q 26.265625 48.484375 22.1875 42.84375 \n",
"Q 18.109375 37.203125 18.109375 27.296875 \n",
"Q 18.109375 17.390625 22.1875 11.75 \n",
"Q 26.265625 6.109375 33.40625 6.109375 \n",
"Q 40.53125 6.109375 44.609375 11.75 \n",
"Q 48.6875 17.390625 48.6875 27.296875 \n",
"z\n",
"M 18.109375 46.390625 \n",
"Q 20.953125 51.265625 25.265625 53.625 \n",
"Q 29.59375 56 35.59375 56 \n",
"Q 45.5625 56 51.78125 48.09375 \n",
"Q 58.015625 40.1875 58.015625 27.296875 \n",
"Q 58.015625 14.40625 51.78125 6.484375 \n",
"Q 45.5625 -1.421875 35.59375 -1.421875 \n",
"Q 29.59375 -1.421875 25.265625 0.953125 \n",
"Q 20.953125 3.328125 18.109375 8.203125 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 75.984375 \n",
"L 18.109375 75.984375 \n",
"z\n",
"\" id=\"DejaVuSans-98\"/>\n",
" <path d=\"M 9.421875 54.6875 \n",
"L 18.40625 54.6875 \n",
"L 18.40625 0 \n",
"L 9.421875 0 \n",
"z\n",
"M 9.421875 75.984375 \n",
"L 18.40625 75.984375 \n",
"L 18.40625 64.59375 \n",
"L 9.421875 64.59375 \n",
"z\n",
"\" id=\"DejaVuSans-105\"/>\n",
" <path d=\"M 18.3125 70.21875 \n",
"L 18.3125 54.6875 \n",
"L 36.8125 54.6875 \n",
"L 36.8125 47.703125 \n",
"L 18.3125 47.703125 \n",
"L 18.3125 18.015625 \n",
"Q 18.3125 11.328125 20.140625 9.421875 \n",
"Q 21.96875 7.515625 27.59375 7.515625 \n",
"L 36.8125 7.515625 \n",
"L 36.8125 0 \n",
"L 27.59375 0 \n",
"Q 17.1875 0 13.234375 3.875 \n",
"Q 9.28125 7.765625 9.28125 18.015625 \n",
"L 9.28125 47.703125 \n",
"L 2.6875 47.703125 \n",
"L 2.6875 54.6875 \n",
"L 9.28125 54.6875 \n",
"L 9.28125 70.21875 \n",
"z\n",
"\" id=\"DejaVuSans-116\"/>\n",
" <path id=\"DejaVuSans-32\"/>\n",
" <path d=\"M 53.515625 70.515625 \n",
"L 53.515625 60.890625 \n",
"Q 47.90625 63.578125 42.921875 64.890625 \n",
"Q 37.9375 66.21875 33.296875 66.21875 \n",
"Q 25.25 66.21875 20.875 63.09375 \n",
"Q 16.5 59.96875 16.5 54.203125 \n",
"Q 16.5 49.359375 19.40625 46.890625 \n",
"Q 22.3125 44.4375 30.421875 42.921875 \n",
"L 36.375 41.703125 \n",
"Q 47.40625 39.59375 52.65625 34.296875 \n",
"Q 57.90625 29 57.90625 20.125 \n",
"Q 57.90625 9.515625 50.796875 4.046875 \n",
"Q 43.703125 -1.421875 29.984375 -1.421875 \n",
"Q 24.8125 -1.421875 18.96875 -0.25 \n",
"Q 13.140625 0.921875 6.890625 3.21875 \n",
"L 6.890625 13.375 \n",
"Q 12.890625 10.015625 18.65625 8.296875 \n",
"Q 24.421875 6.59375 29.984375 6.59375 \n",
"Q 38.421875 6.59375 43.015625 9.90625 \n",
"Q 47.609375 13.234375 47.609375 19.390625 \n",
"Q 47.609375 24.75 44.3125 27.78125 \n",
"Q 41.015625 30.8125 33.5 32.328125 \n",
"L 27.484375 33.5 \n",
"Q 16.453125 35.6875 11.515625 40.375 \n",
"Q 6.59375 45.0625 6.59375 53.421875 \n",
"Q 6.59375 63.09375 13.40625 68.65625 \n",
"Q 20.21875 74.21875 32.171875 74.21875 \n",
"Q 37.3125 74.21875 42.625 73.28125 \n",
"Q 47.953125 72.359375 53.515625 70.515625 \n",
"z\n",
"\" id=\"DejaVuSans-83\"/>\n",
" <path d=\"M 34.28125 27.484375 \n",
"Q 23.390625 27.484375 19.1875 25 \n",
"Q 14.984375 22.515625 14.984375 16.5 \n",
"Q 14.984375 11.71875 18.140625 8.90625 \n",
"Q 21.296875 6.109375 26.703125 6.109375 \n",
"Q 34.1875 6.109375 38.703125 11.40625 \n",
"Q 43.21875 16.703125 43.21875 25.484375 \n",
"L 43.21875 27.484375 \n",
"z\n",
"M 52.203125 31.203125 \n",
"L 52.203125 0 \n",
"L 43.21875 0 \n",
"L 43.21875 8.296875 \n",
"Q 40.140625 3.328125 35.546875 0.953125 \n",
"Q 30.953125 -1.421875 24.3125 -1.421875 \n",
"Q 15.921875 -1.421875 10.953125 3.296875 \n",
"Q 6 8.015625 6 15.921875 \n",
"Q 6 25.140625 12.171875 29.828125 \n",
"Q 18.359375 34.515625 30.609375 34.515625 \n",
"L 43.21875 34.515625 \n",
"L 43.21875 35.40625 \n",
"Q 43.21875 41.609375 39.140625 45 \n",
"Q 35.0625 48.390625 27.6875 48.390625 \n",
"Q 23 48.390625 18.546875 47.265625 \n",
"Q 14.109375 46.140625 10.015625 43.890625 \n",
"L 10.015625 52.203125 \n",
"Q 14.9375 54.109375 19.578125 55.046875 \n",
"Q 24.21875 56 28.609375 56 \n",
"Q 40.484375 56 46.34375 49.84375 \n",
"Q 52.203125 43.703125 52.203125 31.203125 \n",
"z\n",
"\" id=\"DejaVuSans-97\"/>\n",
" <path d=\"M 56.203125 29.59375 \n",
"L 56.203125 25.203125 \n",
"L 14.890625 25.203125 \n",
"Q 15.484375 15.921875 20.484375 11.0625 \n",
"Q 25.484375 6.203125 34.421875 6.203125 \n",
"Q 39.59375 6.203125 44.453125 7.46875 \n",
"Q 49.3125 8.734375 54.109375 11.28125 \n",
"L 54.109375 2.78125 \n",
"Q 49.265625 0.734375 44.1875 -0.34375 \n",
"Q 39.109375 -1.421875 33.890625 -1.421875 \n",
"Q 20.796875 -1.421875 13.15625 6.1875 \n",
"Q 5.515625 13.8125 5.515625 26.8125 \n",
"Q 5.515625 40.234375 12.765625 48.109375 \n",
"Q 20.015625 56 32.328125 56 \n",
"Q 43.359375 56 49.78125 48.890625 \n",
"Q 56.203125 41.796875 56.203125 29.59375 \n",
"z\n",
"M 47.21875 32.234375 \n",
"Q 47.125 39.59375 43.09375 43.984375 \n",
"Q 39.0625 48.390625 32.421875 48.390625 \n",
"Q 24.90625 48.390625 20.390625 44.140625 \n",
"Q 15.875 39.890625 15.1875 32.171875 \n",
"z\n",
"\" id=\"DejaVuSans-101\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-81\"/>\n",
" <use x=\"78.710938\" xlink:href=\"#DejaVuSans-117\"/>\n",
" <use x=\"142.089844\" xlink:href=\"#DejaVuSans-98\"/>\n",
" <use x=\"205.566406\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"233.349609\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"272.558594\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"304.345703\" xlink:href=\"#DejaVuSans-83\"/>\n",
" <use x=\"367.822266\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"407.03125\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"468.310547\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"507.519531\" xlink:href=\"#DejaVuSans-101\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"matplotlib.axis_2\">\n",
" <g id=\"ytick_1\">\n",
" <g id=\"line2d_17\">\n",
" <defs>\n",
" <path d=\"M 0 0 \n",
"L -3.5 0 \n",
"\" id=\"m4322a873f8\" style=\"stroke:#000000;stroke-width:0.8;\"/>\n",
" </defs>\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m4322a873f8\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_18\">\n",
" <!-- 0.0 -->\n",
" <g transform=\"translate(20.878125 228.439219)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 10.6875 12.40625 \n",
"L 21 12.40625 \n",
"L 21 0 \n",
"L 10.6875 0 \n",
"z\n",
"\" id=\"DejaVuSans-46\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_2\">\n",
" <g id=\"line2d_18\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m4322a873f8\" y=\"184.171341\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_19\">\n",
" <!-- 0.1 -->\n",
" <g transform=\"translate(20.878125 187.97056)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_3\">\n",
" <g id=\"line2d_19\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m4322a873f8\" y=\"143.702683\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_20\">\n",
" <!-- 0.2 -->\n",
" <g transform=\"translate(20.878125 147.501901)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 19.1875 8.296875 \n",
"L 53.609375 8.296875 \n",
"L 53.609375 0 \n",
"L 7.328125 0 \n",
"L 7.328125 8.296875 \n",
"Q 12.9375 14.109375 22.625 23.890625 \n",
"Q 32.328125 33.6875 34.8125 36.53125 \n",
"Q 39.546875 41.84375 41.421875 45.53125 \n",
"Q 43.3125 49.21875 43.3125 52.78125 \n",
"Q 43.3125 58.59375 39.234375 62.25 \n",
"Q 35.15625 65.921875 28.609375 65.921875 \n",
"Q 23.96875 65.921875 18.8125 64.3125 \n",
"Q 13.671875 62.703125 7.8125 59.421875 \n",
"L 7.8125 69.390625 \n",
"Q 13.765625 71.78125 18.9375 73 \n",
"Q 24.125 74.21875 28.421875 74.21875 \n",
"Q 39.75 74.21875 46.484375 68.546875 \n",
"Q 53.21875 62.890625 53.21875 53.421875 \n",
"Q 53.21875 48.921875 51.53125 44.890625 \n",
"Q 49.859375 40.875 45.40625 35.40625 \n",
"Q 44.1875 33.984375 37.640625 27.21875 \n",
"Q 31.109375 20.453125 19.1875 8.296875 \n",
"z\n",
"\" id=\"DejaVuSans-50\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-50\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_4\">\n",
" <g id=\"line2d_20\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m4322a873f8\" y=\"103.234024\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_21\">\n",
" <!-- 0.3 -->\n",
" <g transform=\"translate(20.878125 107.033243)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 40.578125 39.3125 \n",
"Q 47.65625 37.796875 51.625 33 \n",
"Q 55.609375 28.21875 55.609375 21.1875 \n",
"Q 55.609375 10.40625 48.1875 4.484375 \n",
"Q 40.765625 -1.421875 27.09375 -1.421875 \n",
"Q 22.515625 -1.421875 17.65625 -0.515625 \n",
"Q 12.796875 0.390625 7.625 2.203125 \n",
"L 7.625 11.71875 \n",
"Q 11.71875 9.328125 16.59375 8.109375 \n",
"Q 21.484375 6.890625 26.8125 6.890625 \n",
"Q 36.078125 6.890625 40.9375 10.546875 \n",
"Q 45.796875 14.203125 45.796875 21.1875 \n",
"Q 45.796875 27.640625 41.28125 31.265625 \n",
"Q 36.765625 34.90625 28.71875 34.90625 \n",
"L 20.21875 34.90625 \n",
"L 20.21875 43.015625 \n",
"L 29.109375 43.015625 \n",
"Q 36.375 43.015625 40.234375 45.921875 \n",
"Q 44.09375 48.828125 44.09375 54.296875 \n",
"Q 44.09375 59.90625 40.109375 62.90625 \n",
"Q 36.140625 65.921875 28.71875 65.921875 \n",
"Q 24.65625 65.921875 20.015625 65.03125 \n",
"Q 15.375 64.15625 9.8125 62.3125 \n",
"L 9.8125 71.09375 \n",
"Q 15.4375 72.65625 20.34375 73.4375 \n",
"Q 25.25 74.21875 29.59375 74.21875 \n",
"Q 40.828125 74.21875 47.359375 69.109375 \n",
"Q 53.90625 64.015625 53.90625 55.328125 \n",
"Q 53.90625 49.265625 50.4375 45.09375 \n",
"Q 46.96875 40.921875 40.578125 39.3125 \n",
"z\n",
"\" id=\"DejaVuSans-51\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-51\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_5\">\n",
" <g id=\"line2d_21\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m4322a873f8\" y=\"62.765365\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_22\">\n",
" <!-- 0.4 -->\n",
" <g transform=\"translate(20.878125 66.564584)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 37.796875 64.3125 \n",
"L 12.890625 25.390625 \n",
"L 37.796875 25.390625 \n",
"z\n",
"M 35.203125 72.90625 \n",
"L 47.609375 72.90625 \n",
"L 47.609375 25.390625 \n",
"L 58.015625 25.390625 \n",
"L 58.015625 17.1875 \n",
"L 47.609375 17.1875 \n",
"L 47.609375 0 \n",
"L 37.796875 0 \n",
"L 37.796875 17.1875 \n",
"L 4.890625 17.1875 \n",
"L 4.890625 26.703125 \n",
"z\n",
"\" id=\"DejaVuSans-52\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-52\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_6\">\n",
" <g id=\"line2d_22\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"43.78125\" xlink:href=\"#m4322a873f8\" y=\"22.296707\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_23\">\n",
" <!-- 0.5 -->\n",
" <g transform=\"translate(20.878125 26.095925)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 10.796875 72.90625 \n",
"L 49.515625 72.90625 \n",
"L 49.515625 64.59375 \n",
"L 19.828125 64.59375 \n",
"L 19.828125 46.734375 \n",
"Q 21.96875 47.46875 24.109375 47.828125 \n",
"Q 26.265625 48.1875 28.421875 48.1875 \n",
"Q 40.625 48.1875 47.75 41.5 \n",
"Q 54.890625 34.8125 54.890625 23.390625 \n",
"Q 54.890625 11.625 47.5625 5.09375 \n",
"Q 40.234375 -1.421875 26.90625 -1.421875 \n",
"Q 22.3125 -1.421875 17.546875 -0.640625 \n",
"Q 12.796875 0.140625 7.71875 1.703125 \n",
"L 7.71875 11.625 \n",
"Q 12.109375 9.234375 16.796875 8.0625 \n",
"Q 21.484375 6.890625 26.703125 6.890625 \n",
"Q 35.15625 6.890625 40.078125 11.328125 \n",
"Q 45.015625 15.765625 45.015625 23.390625 \n",
"Q 45.015625 31 40.078125 35.4375 \n",
"Q 35.15625 39.890625 26.703125 39.890625 \n",
"Q 22.75 39.890625 18.8125 39.015625 \n",
"Q 14.890625 38.140625 10.796875 36.28125 \n",
"z\n",
"\" id=\"DejaVuSans-53\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-53\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_24\">\n",
" <!-- Measured Probabilities -->\n",
" <g transform=\"translate(14.798438 172.470781)rotate(-90)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 9.8125 72.90625 \n",
"L 24.515625 72.90625 \n",
"L 43.109375 23.296875 \n",
"L 61.8125 72.90625 \n",
"L 76.515625 72.90625 \n",
"L 76.515625 0 \n",
"L 66.890625 0 \n",
"L 66.890625 64.015625 \n",
"L 48.09375 14.015625 \n",
"L 38.1875 14.015625 \n",
"L 19.390625 64.015625 \n",
"L 19.390625 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-77\"/>\n",
" <path d=\"M 44.28125 53.078125 \n",
"L 44.28125 44.578125 \n",
"Q 40.484375 46.53125 36.375 47.5 \n",
"Q 32.28125 48.484375 27.875 48.484375 \n",
"Q 21.1875 48.484375 17.84375 46.4375 \n",
"Q 14.5 44.390625 14.5 40.28125 \n",
"Q 14.5 37.15625 16.890625 35.375 \n",
"Q 19.28125 33.59375 26.515625 31.984375 \n",
"L 29.59375 31.296875 \n",
"Q 39.15625 29.25 43.1875 25.515625 \n",
"Q 47.21875 21.78125 47.21875 15.09375 \n",
"Q 47.21875 7.46875 41.1875 3.015625 \n",
"Q 35.15625 -1.421875 24.609375 -1.421875 \n",
"Q 20.21875 -1.421875 15.453125 -0.5625 \n",
"Q 10.6875 0.296875 5.421875 2 \n",
"L 5.421875 11.28125 \n",
"Q 10.40625 8.6875 15.234375 7.390625 \n",
"Q 20.0625 6.109375 24.8125 6.109375 \n",
"Q 31.15625 6.109375 34.5625 8.28125 \n",
"Q 37.984375 10.453125 37.984375 14.40625 \n",
"Q 37.984375 18.0625 35.515625 20.015625 \n",
"Q 33.0625 21.96875 24.703125 23.78125 \n",
"L 21.578125 24.515625 \n",
"Q 13.234375 26.265625 9.515625 29.90625 \n",
"Q 5.8125 33.546875 5.8125 39.890625 \n",
"Q 5.8125 47.609375 11.28125 51.796875 \n",
"Q 16.75 56 26.8125 56 \n",
"Q 31.78125 56 36.171875 55.265625 \n",
"Q 40.578125 54.546875 44.28125 53.078125 \n",
"z\n",
"\" id=\"DejaVuSans-115\"/>\n",
" <path d=\"M 41.109375 46.296875 \n",
"Q 39.59375 47.171875 37.8125 47.578125 \n",
"Q 36.03125 48 33.890625 48 \n",
"Q 26.265625 48 22.1875 43.046875 \n",
"Q 18.109375 38.09375 18.109375 28.8125 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 54.6875 \n",
"L 18.109375 54.6875 \n",
"L 18.109375 46.1875 \n",
"Q 20.953125 51.171875 25.484375 53.578125 \n",
"Q 30.03125 56 36.53125 56 \n",
"Q 37.453125 56 38.578125 55.875 \n",
"Q 39.703125 55.765625 41.0625 55.515625 \n",
"z\n",
"\" id=\"DejaVuSans-114\"/>\n",
" <path d=\"M 45.40625 46.390625 \n",
"L 45.40625 75.984375 \n",
"L 54.390625 75.984375 \n",
"L 54.390625 0 \n",
"L 45.40625 0 \n",
"L 45.40625 8.203125 \n",
"Q 42.578125 3.328125 38.25 0.953125 \n",
"Q 33.9375 -1.421875 27.875 -1.421875 \n",
"Q 17.96875 -1.421875 11.734375 6.484375 \n",
"Q 5.515625 14.40625 5.515625 27.296875 \n",
"Q 5.515625 40.1875 11.734375 48.09375 \n",
"Q 17.96875 56 27.875 56 \n",
"Q 33.9375 56 38.25 53.625 \n",
"Q 42.578125 51.265625 45.40625 46.390625 \n",
"z\n",
"M 14.796875 27.296875 \n",
"Q 14.796875 17.390625 18.875 11.75 \n",
"Q 22.953125 6.109375 30.078125 6.109375 \n",
"Q 37.203125 6.109375 41.296875 11.75 \n",
"Q 45.40625 17.390625 45.40625 27.296875 \n",
"Q 45.40625 37.203125 41.296875 42.84375 \n",
"Q 37.203125 48.484375 30.078125 48.484375 \n",
"Q 22.953125 48.484375 18.875 42.84375 \n",
"Q 14.796875 37.203125 14.796875 27.296875 \n",
"z\n",
"\" id=\"DejaVuSans-100\"/>\n",
" <path d=\"M 19.671875 64.796875 \n",
"L 19.671875 37.40625 \n",
"L 32.078125 37.40625 \n",
"Q 38.96875 37.40625 42.71875 40.96875 \n",
"Q 46.484375 44.53125 46.484375 51.125 \n",
"Q 46.484375 57.671875 42.71875 61.234375 \n",
"Q 38.96875 64.796875 32.078125 64.796875 \n",
"z\n",
"M 9.8125 72.90625 \n",
"L 32.078125 72.90625 \n",
"Q 44.34375 72.90625 50.609375 67.359375 \n",
"Q 56.890625 61.8125 56.890625 51.125 \n",
"Q 56.890625 40.328125 50.609375 34.8125 \n",
"Q 44.34375 29.296875 32.078125 29.296875 \n",
"L 19.671875 29.296875 \n",
"L 19.671875 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-80\"/>\n",
" <path d=\"M 30.609375 48.390625 \n",
"Q 23.390625 48.390625 19.1875 42.75 \n",
"Q 14.984375 37.109375 14.984375 27.296875 \n",
"Q 14.984375 17.484375 19.15625 11.84375 \n",
"Q 23.34375 6.203125 30.609375 6.203125 \n",
"Q 37.796875 6.203125 41.984375 11.859375 \n",
"Q 46.1875 17.53125 46.1875 27.296875 \n",
"Q 46.1875 37.015625 41.984375 42.703125 \n",
"Q 37.796875 48.390625 30.609375 48.390625 \n",
"z\n",
"M 30.609375 56 \n",
"Q 42.328125 56 49.015625 48.375 \n",
"Q 55.71875 40.765625 55.71875 27.296875 \n",
"Q 55.71875 13.875 49.015625 6.21875 \n",
"Q 42.328125 -1.421875 30.609375 -1.421875 \n",
"Q 18.84375 -1.421875 12.171875 6.21875 \n",
"Q 5.515625 13.875 5.515625 27.296875 \n",
"Q 5.515625 40.765625 12.171875 48.375 \n",
"Q 18.84375 56 30.609375 56 \n",
"z\n",
"\" id=\"DejaVuSans-111\"/>\n",
" <path d=\"M 9.421875 75.984375 \n",
"L 18.40625 75.984375 \n",
"L 18.40625 0 \n",
"L 9.421875 0 \n",
"z\n",
"\" id=\"DejaVuSans-108\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-77\"/>\n",
" <use x=\"86.279297\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"147.802734\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"209.082031\" xlink:href=\"#DejaVuSans-115\"/>\n",
" <use x=\"261.181641\" xlink:href=\"#DejaVuSans-117\"/>\n",
" <use x=\"324.560547\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"363.423828\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"424.947266\" xlink:href=\"#DejaVuSans-100\"/>\n",
" <use x=\"488.423828\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"520.210938\" xlink:href=\"#DejaVuSans-80\"/>\n",
" <use x=\"578.763672\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"617.626953\" xlink:href=\"#DejaVuSans-111\"/>\n",
" <use x=\"678.808594\" xlink:href=\"#DejaVuSans-98\"/>\n",
" <use x=\"742.285156\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"803.564453\" xlink:href=\"#DejaVuSans-98\"/>\n",
" <use x=\"867.041016\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"894.824219\" xlink:href=\"#DejaVuSans-108\"/>\n",
" <use x=\"922.607422\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"950.390625\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"989.599609\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"1017.382812\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"1078.90625\" xlink:href=\"#DejaVuSans-115\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"patch_19\">\n",
" <path d=\"M 43.78125 224.64 \n",
"L 43.78125 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_20\">\n",
" <path d=\"M 378.58125 224.64 \n",
"L 378.58125 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_21\">\n",
" <path d=\"M 43.78125 224.64 \n",
"L 378.58125 224.64 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_22\">\n",
" <path d=\"M 43.78125 7.2 \n",
"L 378.58125 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <defs>\n",
" <clipPath id=\"p1913dbb0ed\">\n",
" <rect height=\"217.44\" width=\"334.8\" x=\"43.78125\" y=\"7.2\"/>\n",
" </clipPath>\n",
" </defs>\n",
"</svg>\n"
],
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -2041,9 +767,8 @@ ...@@ -2041,9 +767,8 @@
} }
], ],
"source": [ "source": [
"with fluid.dygraph.guard():\n", "# Repeat the simulated measurement of the circuit output state 1024 times\n",
" # Repeat the simulated measurement of the circuit output state 1024 times\n", "prob_measure = cir.measure(plot=True)"
" prob_measure = cir.measure(plot=True)"
] ]
}, },
{ {
...@@ -2063,8 +788,8 @@ ...@@ -2063,8 +788,8 @@
"execution_count": 10, "execution_count": 10,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T06:55:10.459840Z", "end_time": "2021-03-09T06:11:08.356970Z",
"start_time": "2021-01-09T06:55:10.334585Z" "start_time": "2021-03-09T06:11:08.052122Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -2077,216 +802,7 @@ ...@@ -2077,216 +802,7 @@
}, },
{ {
"data": { "data": {
"image/svg+xml": [ "image/png": "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\n",
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Created with matplotlib (https://matplotlib.org/) -->\n",
"<svg height=\"302.4pt\" version=\"1.1\" viewBox=\"0 0 446.4 302.4\" width=\"446.4pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
" <metadata>\n",
" <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
" <cc:Work>\n",
" <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
" <dc:date>2021-01-09T14:55:10.428597</dc:date>\n",
" <dc:format>image/svg+xml</dc:format>\n",
" <dc:creator>\n",
" <cc:Agent>\n",
" <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\n",
" </cc:Agent>\n",
" </dc:creator>\n",
" </cc:Work>\n",
" </rdf:RDF>\n",
" </metadata>\n",
" <defs>\n",
" <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n",
" </defs>\n",
" <g id=\"figure_1\">\n",
" <g id=\"patch_1\">\n",
" <path d=\"M 0 302.4 \n",
"L 446.4 302.4 \n",
"L 446.4 0 \n",
"L 0 0 \n",
"z\n",
"\" style=\"fill:#ffffff;\"/>\n",
" </g>\n",
" <g id=\"axes_1\">\n",
" <g id=\"LineCollection_1\">\n",
" <path clip-path=\"url(#p98894c64dc)\" d=\"M 377.485714 151.2 \n",
"L 223.199993 48.342857 \n",
"\" style=\"fill:none;stroke:#000000;stroke-dasharray:7.4,3.2;stroke-dashoffset:0;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#p98894c64dc)\" d=\"M 377.485714 151.2 \n",
"L 223.200002 254.057143 \n",
"\" style=\"fill:none;stroke:#000000;stroke-dasharray:7.4,3.2;stroke-dashoffset:0;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#p98894c64dc)\" d=\"M 223.199993 48.342857 \n",
"L 68.914286 151.200009 \n",
"\" style=\"fill:none;stroke:#000000;stroke-dasharray:7.4,3.2;stroke-dashoffset:0;stroke-width:2;\"/>\n",
" <path clip-path=\"url(#p98894c64dc)\" d=\"M 68.914286 151.200009 \n",
"L 223.200002 254.057143 \n",
"\" style=\"fill:none;stroke:#000000;stroke-dasharray:7.4,3.2;stroke-dashoffset:0;stroke-width:2;\"/>\n",
" </g>\n",
" <g id=\"PathCollection_1\">\n",
" <defs>\n",
" <path d=\"M 0 22.36068 \n",
"C 5.930122 22.36068 11.618159 20.004617 15.811388 15.811388 \n",
"C 20.004617 11.618159 22.36068 5.930122 22.36068 -0 \n",
"C 22.36068 -5.930122 20.004617 -11.618159 15.811388 -15.811388 \n",
"C 11.618159 -20.004617 5.930122 -22.36068 0 -22.36068 \n",
"C -5.930122 -22.36068 -11.618159 -20.004617 -15.811388 -15.811388 \n",
"C -20.004617 -11.618159 -22.36068 -5.930122 -22.36068 0 \n",
"C -22.36068 5.930122 -20.004617 11.618159 -15.811388 15.811388 \n",
"C -11.618159 20.004617 -5.930122 22.36068 0 22.36068 \n",
"z\n",
"\" id=\"C0_0_c7785b86ce\"/>\n",
" </defs>\n",
" <g clip-path=\"url(#p98894c64dc)\">\n",
" <use style=\"fill:#0000ff;stroke:#0000ff;\" x=\"377.485714\" xlink:href=\"#C0_0_c7785b86ce\" y=\"151.2\"/>\n",
" </g>\n",
" <g clip-path=\"url(#p98894c64dc)\">\n",
" <use style=\"fill:#ff0000;stroke:#ff0000;\" x=\"223.199993\" xlink:href=\"#C0_0_c7785b86ce\" y=\"48.342857\"/>\n",
" </g>\n",
" <g clip-path=\"url(#p98894c64dc)\">\n",
" <use style=\"fill:#0000ff;stroke:#0000ff;\" x=\"68.914286\" xlink:href=\"#C0_0_c7785b86ce\" y=\"151.200009\"/>\n",
" </g>\n",
" <g clip-path=\"url(#p98894c64dc)\">\n",
" <use style=\"fill:#ff0000;stroke:#ff0000;\" x=\"223.200002\" xlink:href=\"#C0_0_c7785b86ce\" y=\"254.057143\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_1\">\n",
" <g clip-path=\"url(#p98894c64dc)\">\n",
" <!-- 0 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(370.527902 156.71875)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 46 36.53125 \n",
"Q 46 50.203125 43.4375 55.78125 \n",
"Q 40.875 61.375 34.8125 61.375 \n",
"Q 28.765625 61.375 26.171875 55.78125 \n",
"Q 23.578125 50.203125 23.578125 36.53125 \n",
"Q 23.578125 22.703125 26.171875 17.03125 \n",
"Q 28.765625 11.375 34.8125 11.375 \n",
"Q 40.828125 11.375 43.40625 17.03125 \n",
"Q 46 22.703125 46 36.53125 \n",
"z\n",
"M 64.796875 36.375 \n",
"Q 64.796875 18.265625 56.984375 8.421875 \n",
"Q 49.171875 -1.421875 34.8125 -1.421875 \n",
"Q 20.40625 -1.421875 12.59375 8.421875 \n",
"Q 4.78125 18.265625 4.78125 36.375 \n",
"Q 4.78125 54.546875 12.59375 64.375 \n",
"Q 20.40625 74.21875 34.8125 74.21875 \n",
"Q 49.171875 74.21875 56.984375 64.375 \n",
"Q 64.796875 54.546875 64.796875 36.375 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-48\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_2\">\n",
" <g clip-path=\"url(#p98894c64dc)\">\n",
" <!-- 1 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(216.242181 53.861607)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 11.71875 12.984375 \n",
"L 28.328125 12.984375 \n",
"L 28.328125 60.109375 \n",
"L 11.28125 56.59375 \n",
"L 11.28125 69.390625 \n",
"L 28.21875 72.90625 \n",
"L 46.09375 72.90625 \n",
"L 46.09375 12.984375 \n",
"L 62.703125 12.984375 \n",
"L 62.703125 0 \n",
"L 11.71875 0 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-49\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-49\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_3\">\n",
" <g clip-path=\"url(#p98894c64dc)\">\n",
" <!-- 2 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(61.956473 156.718759)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 28.8125 13.8125 \n",
"L 60.890625 13.8125 \n",
"L 60.890625 0 \n",
"L 7.90625 0 \n",
"L 7.90625 13.8125 \n",
"L 34.515625 37.3125 \n",
"Q 38.09375 40.53125 39.796875 43.609375 \n",
"Q 41.5 46.6875 41.5 50 \n",
"Q 41.5 55.125 38.0625 58.25 \n",
"Q 34.625 61.375 28.90625 61.375 \n",
"Q 24.515625 61.375 19.28125 59.5 \n",
"Q 14.0625 57.625 8.109375 53.90625 \n",
"L 8.109375 69.921875 \n",
"Q 14.453125 72.015625 20.65625 73.109375 \n",
"Q 26.859375 74.21875 32.8125 74.21875 \n",
"Q 45.90625 74.21875 53.15625 68.453125 \n",
"Q 60.40625 62.703125 60.40625 52.390625 \n",
"Q 60.40625 46.4375 57.328125 41.28125 \n",
"Q 54.25 36.140625 44.390625 27.484375 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-50\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-50\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_4\">\n",
" <g clip-path=\"url(#p98894c64dc)\">\n",
" <!-- 3 -->\n",
" <g style=\"fill:#ffffff;\" transform=\"translate(216.242189 259.575893)scale(0.2 -0.2)\">\n",
" <defs>\n",
" <path d=\"M 46.578125 39.3125 \n",
"Q 53.953125 37.40625 57.78125 32.6875 \n",
"Q 61.625 27.984375 61.625 20.703125 \n",
"Q 61.625 9.859375 53.3125 4.21875 \n",
"Q 45.015625 -1.421875 29.109375 -1.421875 \n",
"Q 23.484375 -1.421875 17.84375 -0.515625 \n",
"Q 12.203125 0.390625 6.6875 2.203125 \n",
"L 6.6875 16.703125 \n",
"Q 11.96875 14.0625 17.15625 12.71875 \n",
"Q 22.359375 11.375 27.390625 11.375 \n",
"Q 34.859375 11.375 38.84375 13.953125 \n",
"Q 42.828125 16.546875 42.828125 21.390625 \n",
"Q 42.828125 26.375 38.75 28.9375 \n",
"Q 34.671875 31.5 26.703125 31.5 \n",
"L 19.1875 31.5 \n",
"L 19.1875 43.609375 \n",
"L 27.09375 43.609375 \n",
"Q 34.1875 43.609375 37.640625 45.828125 \n",
"Q 41.109375 48.046875 41.109375 52.59375 \n",
"Q 41.109375 56.78125 37.734375 59.078125 \n",
"Q 34.375 61.375 28.21875 61.375 \n",
"Q 23.6875 61.375 19.046875 60.34375 \n",
"Q 14.40625 59.328125 9.8125 57.328125 \n",
"L 9.8125 71.09375 \n",
"Q 15.375 72.65625 20.84375 73.4375 \n",
"Q 26.3125 74.21875 31.59375 74.21875 \n",
"Q 45.796875 74.21875 52.84375 69.546875 \n",
"Q 59.90625 64.890625 59.90625 55.515625 \n",
"Q 59.90625 49.125 56.53125 45.046875 \n",
"Q 53.171875 40.96875 46.578125 39.3125 \n",
"z\n",
"\" id=\"DejaVuSans-Bold-51\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-Bold-51\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <defs>\n",
" <clipPath id=\"p98894c64dc\">\n",
" <rect height=\"288\" width=\"432\" x=\"7.2\" y=\"7.2\"/>\n",
" </clipPath>\n",
" </defs>\n",
"</svg>\n"
],
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -2339,7 +855,7 @@ ...@@ -2339,7 +855,7 @@
"\n", "\n",
"[2] Farhi, E., Goldstone, J., Gutmann, S. & Sipser, M. Quantum computation by adiabatic evolution. [arXiv:quant-ph/0001106 (2000).](https://arxiv.org/abs/quant-ph/0001106)\n", "[2] Farhi, E., Goldstone, J., Gutmann, S. & Sipser, M. Quantum computation by adiabatic evolution. [arXiv:quant-ph/0001106 (2000).](https://arxiv.org/abs/quant-ph/0001106)\n",
"\n", "\n",
"[3] Duan, R. Quantum Adiabatic Theorem Revisited. [arXiv:2003.03063 (2020).](https://arxiv.org/abs/2003.03063)\n" "[3] Duan, R. Quantum Adiabatic Theorem Revisited. [arXiv:2003.03063 (2020).](https://arxiv.org/abs/2003.03063)"
] ]
} }
], ],
...@@ -2359,7 +875,7 @@ ...@@ -2359,7 +875,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.10" "version": "3.7.0"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
...@@ -2378,6 +894,35 @@ ...@@ -2378,6 +894,35 @@
}, },
"toc_section_display": true, "toc_section_display": true,
"toc_window_display": true "toc_window_display": true
},
"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
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -20,15 +20,16 @@ ...@@ -20,15 +20,16 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:59.183983Z", "end_time": "2021-03-09T03:40:57.525085Z",
"start_time": "2021-01-09T10:39:55.833348Z" "start_time": "2021-03-09T03:40:54.923948Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy\n", "import numpy\n",
"from paddle.complex import matmul, transpose\n", "from numpy import pi as PI\n",
"from paddle import fluid\n", "import paddle \n",
"from paddle import matmul\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import random_pauli_str_generator, pauli_str_to_matrix, dagger" "from paddle_quantum.utils import random_pauli_str_generator, pauli_str_to_matrix, dagger"
] ]
...@@ -54,14 +55,14 @@ ...@@ -54,14 +55,14 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:59.199187Z", "end_time": "2021-03-09T03:40:57.538850Z",
"start_time": "2021-01-09T10:39:59.189011Z" "start_time": "2021-03-09T03:40:57.527973Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"N = 2 # 量子比特数/量子神经网络的宽度 \n", "N = 2 # 量子比特数/量子神经网络的宽度\n",
"SEED = 14 # 固定随机种子" "SEED = 14 # 固定随机种子"
] ]
}, },
{ {
...@@ -69,8 +70,8 @@ ...@@ -69,8 +70,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:59.240622Z", "end_time": "2021-03-09T03:40:57.556193Z",
"start_time": "2021-01-09T10:39:59.205845Z" "start_time": "2021-03-09T03:40:57.544832Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -79,12 +80,13 @@ ...@@ -79,12 +80,13 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Random Hamiltonian in Pauli string format = \n", "Random Hamiltonian in Pauli string format = \n",
" [[-0.12086078882948925, 'z0,y1'], [0.8520481243020479, 'x0'], [0.7311915310296655, 'x1'], [0.8878180549783599, 'x1'], [-0.07152647722934247, 'z0'], [0.36890035805078325, 'z1,z0'], [-0.47650461185021764, 'z1,y0'], [0.957686278969355, 'z0,y1'], [-0.4742145513250544, 'y0'], [-0.30811279345705755, 'x1']]\n" " [[0.9152074787317819, 'x1,y0'], [-0.2717604556798945, 'z0'], [0.3628495008719168, 'x0'], [-0.5050129214094752, 'x1'], [-0.6971554357833791, 'y0,x1'], [0.8651151857574237, 'x0,y1'], [0.7409989105435002, 'y0'], [-0.39981603921243236, 'y0'], [0.06862640764702, 'z0'], [-0.7647553733438246, 'y1']]\n"
] ]
} }
], ],
"source": [ "source": [
"# 生成用泡利字符串表示的随机 Hamilton 量\n", "# 生成用泡利字符串表示的随机 Hamilton 量\n",
"numpy.random.seed(SEED)\n",
"hamiltonian = random_pauli_str_generator(N, terms=10)\n", "hamiltonian = random_pauli_str_generator(N, terms=10)\n",
"print(\"Random Hamiltonian in Pauli string format = \\n\", hamiltonian)\n", "print(\"Random Hamiltonian in Pauli string format = \\n\", hamiltonian)\n",
"\n", "\n",
...@@ -108,8 +110,8 @@ ...@@ -108,8 +110,8 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:59.272186Z", "end_time": "2021-03-09T03:40:57.570458Z",
"start_time": "2021-01-09T10:39:59.255438Z" "start_time": "2021-03-09T03:40:57.559295Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -154,19 +156,20 @@ ...@@ -154,19 +156,20 @@
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:59.308410Z", "end_time": "2021-03-09T03:40:58.810111Z",
"start_time": "2021-01-09T10:39:59.285372Z" "start_time": "2021-03-09T03:40:58.794879Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Net(fluid.dygraph.Layer):\n", "class Net(paddle.nn.Layer):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * numpy.pi, seed=SEED), dtype='float64'):\n", " def __init__(self, shape, dtype='float64'):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
" \n", " \n",
" # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n", " # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n",
" self.theta = self.create_parameter(shape=shape, \n", " self.theta = self.create_parameter(shape=shape,\n",
" attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # 定义损失函数和前向传播机制\n", " # 定义损失函数和前向传播机制\n",
" def forward(self, H, N):\n", " def forward(self, H, N):\n",
...@@ -175,7 +178,7 @@ ...@@ -175,7 +178,7 @@
" U = U_theta(self.theta, N)\n", " U = U_theta(self.theta, N)\n",
" \n", " \n",
" # 计算损失函数\n", " # 计算损失函数\n",
" loss_struct = matmul(matmul(dagger(U), H), U).real\n", " loss_struct = paddle.real(matmul(matmul(dagger(U), H), U))\n",
"\n", "\n",
" # 输入计算基去计算每个子期望值,相当于取 U^dagger*H*U 的对角元 \n", " # 输入计算基去计算每个子期望值,相当于取 U^dagger*H*U 的对角元 \n",
" loss_components = [\n", " loss_components = [\n",
...@@ -205,13 +208,13 @@ ...@@ -205,13 +208,13 @@
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:59.327673Z", "end_time": "2021-03-09T03:41:00.676449Z",
"start_time": "2021-01-09T10:39:59.322589Z" "start_time": "2021-03-09T03:41:00.667746Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"ITR = 50 # 设置训练的总迭代次数\n", "ITR = 100 # 设置训练的总迭代次数\n",
"LR = 0.3 # 设置学习速率" "LR = 0.3 # 设置学习速率"
] ]
}, },
...@@ -220,7 +223,7 @@ ...@@ -220,7 +223,7 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"## 进行训练\n", "## 进行训练\n",
"- 当训练模型的各项参数都设置完成后,我们将数据转化为 PaddlePaddle 动态图中的量,进而进行量子神经网络的训练。\n", "- 当训练模型的各项参数都设置完成后,我们将数据转化为 PaddlePaddle 动态图中的量,进而进行量子神经网络的训练。\n",
"- 过程中我们用的是 Adam Optimizer,也可以调用 PaddlePaddle 中提供的其他优化器。\n", "- 过程中我们用的是 Adam Optimizer,也可以调用 PaddlePaddle 中提供的其他优化器。\n",
"- 我们可以将训练过程中的每一轮 loss 打印出来。" "- 我们可以将训练过程中的每一轮 loss 打印出来。"
] ]
...@@ -230,8 +233,8 @@ ...@@ -230,8 +233,8 @@
"execution_count": 7, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:40:01.356487Z", "end_time": "2021-03-09T03:41:11.696116Z",
"start_time": "2021-01-09T10:39:59.332679Z" "start_time": "2021-03-09T03:41:08.683371Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -239,42 +242,46 @@ ...@@ -239,42 +242,46 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 10 loss: -6.1446\n", "iter: 10 loss: -4.5668\n",
"iter: 20 loss: -7.7827\n", "iter: 20 loss: -5.3998\n",
"iter: 30 loss: -8.0978\n", "iter: 30 loss: -5.6210\n",
"iter: 40 loss: -8.4615\n", "iter: 40 loss: -5.8872\n",
"iter: 50 loss: -8.4589\n" "iter: 50 loss: -5.9246\n",
"iter: 60 loss: -5.9471\n",
"iter: 70 loss: -5.9739\n",
"iter: 80 loss: -5.9833\n",
"iter: 90 loss: -5.9846\n",
"iter: 100 loss: -5.9848\n"
] ]
} }
], ],
"source": [ "source": [
"# 初始化paddle动态图机制\n", "paddle.seed(SEED)\n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" # 我们需要将 numpy.ndarray 转换成 PaddlePaddle 动态图模式中支持的 variable\n", "# 我们需要将 numpy.ndarray 转换成 PaddlePaddle 支持的 Tensor\n",
" hamiltonian = fluid.dygraph.to_variable(H)\n", "hamiltonian = paddle.to_tensor(H)\n",
"\n", "\n",
" # 确定网络的参数维度\n", "# 确定网络的参数维度\n",
" net = Net(shape=[THETA_SIZE])\n", "net = Net(shape=[THETA_SIZE])\n",
"\n", "\n",
" # 一般来说,我们利用 Adam 优化器来获得相对好的收敛,\n", "# 一般来说,我们利用 Adam 优化器来获得相对好的收敛,\n",
" # 当然你可以改成 SGD 或者是 RMS prop.\n", "# 当然你可以改成 SGD 或者是 RMS prop.\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"\n", "\n",
" # 优化循环\n", "# 优化循环\n",
" for itr in range(1, ITR + 1):\n", "for itr in range(1, ITR + 1):\n",
" \n", "\n",
" # 前向传播计算损失函数并返回估计的能谱\n", " # 前向传播计算损失函数并返回估计的能谱\n",
" loss, loss_components = net(hamiltonian, N)\n", " loss, loss_components = net(hamiltonian, N)\n",
" \n", "\n",
" # 在动态图机制下,反向传播极小化损失函数\n", " # 在动态图机制下,反向传播极小化损失函数\n",
" loss.backward()\n", " loss.backward()\n",
" opt.minimize(loss)\n", " opt.minimize(loss)\n",
" net.clear_gradients()\n", " opt.clear_grad()\n",
" \n", "\n",
" # 打印训练结果\n", " # 打印训练结果\n",
" if itr % 10 == 0:\n", " if itr % 10 == 0:\n",
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])" " print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])"
] ]
}, },
{ {
...@@ -294,8 +301,8 @@ ...@@ -294,8 +301,8 @@
"execution_count": 8, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:40:01.398375Z", "end_time": "2021-03-09T03:41:14.595062Z",
"start_time": "2021-01-09T10:40:01.375160Z" "start_time": "2021-03-09T03:41:14.562037Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -303,14 +310,14 @@ ...@@ -303,14 +310,14 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"The estimated ground state energy is: [-2.3665305]\n", "The estimated ground state energy is: [-2.18762367]\n",
"The theoretical ground state energy: -2.385744737010799\n", "The theoretical ground state energy: -2.18790201165885\n",
"The estimated 1st excited state energy is: [-1.34818389]\n", "The estimated 1st excited state energy is: [-0.13721027]\n",
"The theoretical 1st excited state energy: -1.3356376227295346\n", "The theoretical 1st excited state energy: -0.13704127143749587\n",
"The estimated 2nd excited state energy is: [1.337023]\n", "The estimated 2nd excited state energy is: [0.85251458]\n",
"The theoretical 2nd excited state energy: 1.3356376227295335\n", "The theoretical 2nd excited state energy: 0.8523274042087416\n",
"The estimated 3rd excited state energy is: [2.37769139]\n", "The estimated 3rd excited state energy is: [1.47231937]\n",
"The theoretical 3rd excited state energy: 2.3857447370107985\n" "The theoretical 3rd excited state energy: 1.4726158788876045\n"
] ]
} }
], ],
...@@ -365,7 +372,7 @@ ...@@ -365,7 +372,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.0" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -20,15 +20,16 @@ ...@@ -20,15 +20,16 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:44.905642Z", "end_time": "2021-03-09T03:41:35.275034Z",
"start_time": "2021-01-09T10:39:40.689291Z" "start_time": "2021-03-09T03:41:30.979161Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy\n", "import numpy\n",
"from paddle.complex import matmul, transpose\n", "from numpy import pi as PI\n",
"from paddle import fluid\n", "import paddle \n",
"from paddle import matmul\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import random_pauli_str_generator, pauli_str_to_matrix, dagger" "from paddle_quantum.utils import random_pauli_str_generator, pauli_str_to_matrix, dagger"
] ]
...@@ -53,14 +54,14 @@ ...@@ -53,14 +54,14 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:44.922274Z", "end_time": "2021-03-09T03:41:35.325305Z",
"start_time": "2021-01-09T10:39:44.908600Z" "start_time": "2021-03-09T03:41:35.308814Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"N = 2 # Number of qubits\n", "N = 2 # Number of qubits\n",
"SEED = 14 # Fixed random seed" "SEED = 14 # Fixed random seed"
] ]
}, },
{ {
...@@ -68,8 +69,8 @@ ...@@ -68,8 +69,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:44.938897Z", "end_time": "2021-03-09T03:41:35.352514Z",
"start_time": "2021-01-09T10:39:44.926267Z" "start_time": "2021-03-09T03:41:35.329030Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -78,12 +79,13 @@ ...@@ -78,12 +79,13 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Random Hamiltonian in Pauli string format = \n", "Random Hamiltonian in Pauli string format = \n",
" [[0.5607206331858847, 'z0'], [-0.9931668020533528, 'z1'], [-0.6264392463826307, 'x1,x0'], [-0.8167732501071665, 'x1,x0'], [0.6792869149087406, 'y0'], [-0.8907888336706506, 'z1,y0'], [0.7878221587000573, 'y1'], [-0.9925516732999857, 'z0,y1'], [-0.7987244836834173, 'x1'], [-0.3124885350069655, 'z0']]\n" " [[0.9152074787317819, 'x1,y0'], [-0.2717604556798945, 'z0'], [0.3628495008719168, 'x0'], [-0.5050129214094752, 'x1'], [-0.6971554357833791, 'y0,x1'], [0.8651151857574237, 'x0,y1'], [0.7409989105435002, 'y0'], [-0.39981603921243236, 'y0'], [0.06862640764702, 'z0'], [-0.7647553733438246, 'y1']]\n"
] ]
} }
], ],
"source": [ "source": [
"# Generate random Hamiltonian represented by Pauli string\n", "# Generate random Hamiltonian represented by Pauli string\n",
"numpy.random.seed(SEED)\n",
"hamiltonian = random_pauli_str_generator(N, terms=10)\n", "hamiltonian = random_pauli_str_generator(N, terms=10)\n",
"print(\"Random Hamiltonian in Pauli string format = \\n\", hamiltonian)\n", "print(\"Random Hamiltonian in Pauli string format = \\n\", hamiltonian)\n",
"\n", "\n",
...@@ -107,8 +109,8 @@ ...@@ -107,8 +109,8 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:44.955929Z", "end_time": "2021-03-09T03:41:35.375932Z",
"start_time": "2021-01-09T10:39:44.950527Z" "start_time": "2021-03-09T03:41:35.358359Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -153,19 +155,20 @@ ...@@ -153,19 +155,20 @@
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:44.972097Z", "end_time": "2021-03-09T03:41:35.410903Z",
"start_time": "2021-01-09T10:39:44.958878Z" "start_time": "2021-03-09T03:41:35.382213Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class Net(fluid.dygraph.Layer):\n", "class Net(paddle.nn.Layer):\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * numpy.pi, seed=SEED), dtype='float64'):\n", " def __init__(self, shape, dtype='float64'):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
" \n", " \n",
" # Initialize the theta parameter list and fill the initial value with the uniform distribution of [0, 2*pi]\n", " # Initialize the theta parameter list and fill the initial value with the uniform distribution of [0, 2*pi]\n",
" self.theta = self.create_parameter(shape=shape,\n", " self.theta = self.create_parameter(shape=shape,\n",
" attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self, H, N):\n", " def forward(self, H, N):\n",
...@@ -174,7 +177,7 @@ ...@@ -174,7 +177,7 @@
" U = U_theta(self.theta, N)\n", " U = U_theta(self.theta, N)\n",
" \n", " \n",
" # Calculate the loss function\n", " # Calculate the loss function\n",
" loss_struct = matmul(matmul(dagger(U), H), U).real\n", " loss_struct = paddle.real(matmul(matmul(dagger(U), H), U))\n",
"\n", "\n",
" # Enter the computational basis to calculate the expected value \n", " # Enter the computational basis to calculate the expected value \n",
" # which is equivalent to taking the diagonal element of U^dagger*H*U\n", " # which is equivalent to taking the diagonal element of U^dagger*H*U\n",
...@@ -206,13 +209,13 @@ ...@@ -206,13 +209,13 @@
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:44.981182Z", "end_time": "2021-03-09T03:41:35.422337Z",
"start_time": "2021-01-09T10:39:44.975407Z" "start_time": "2021-03-09T03:41:35.417772Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"ITR = 50 # Set the total number of iterations of training\n", "ITR = 100 # Set the total number of iterations of training\n",
"LR = 0.3 # Set the learning rate" "LR = 0.3 # Set the learning rate"
] ]
}, },
...@@ -222,17 +225,17 @@ ...@@ -222,17 +225,17 @@
"source": [ "source": [
"## Training process\n", "## Training process\n",
"\n", "\n",
"- After setting all the parameters of SSVQE model, we need to convert all the data into variables in the PaddlePaddle dynamic graph, and then train the quantum neural network.\n", "- After setting all the parameters of SSVQE model, we need to convert all the data into Tensor in the PaddlePaddle, and then train the quantum neural network.\n",
"- We use Adam Optimizer in training, and one can also call other optimizers provided in PaddlePaddle." "- We use Adam Optimizer in training, and one can also call other optimizers provided in PaddlePaddle."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:46.247964Z", "end_time": "2021-03-09T03:41:43.095334Z",
"start_time": "2021-01-09T10:39:44.985154Z" "start_time": "2021-03-09T03:41:40.517746Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -240,42 +243,46 @@ ...@@ -240,42 +243,46 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 10 loss: -8.9318\n", "iter: 10 loss: -4.5668\n",
"iter: 20 loss: -10.5747\n", "iter: 20 loss: -5.3998\n",
"iter: 30 loss: -11.0288\n", "iter: 30 loss: -5.6210\n",
"iter: 40 loss: -11.2393\n", "iter: 40 loss: -5.8872\n",
"iter: 50 loss: -11.3251\n" "iter: 50 loss: -5.9246\n",
"iter: 60 loss: -5.9471\n",
"iter: 70 loss: -5.9739\n",
"iter: 80 loss: -5.9833\n",
"iter: 90 loss: -5.9846\n",
"iter: 100 loss: -5.9848\n"
] ]
} }
], ],
"source": [ "source": [
"# Initialize paddle dynamic graph mode\n", "paddle.seed(SEED)\n",
"with fluid.dygraph.guard():\n",
" \n",
" # We need to convert numpy.ndarray to variable supported in Paddle dynamic graph mode\n",
" hamiltonian = fluid.dygraph.to_variable(H)\n",
"\n", "\n",
" # Determine the parameter dimension of the network\n", "# We need to convert numpy.ndarray to Tensor supported in Paddle\n",
" net = Net(shape=[THETA_SIZE])\n", "hamiltonian = paddle.to_tensor(H)\n",
"\n", "\n",
" # We use Adam optimizer for better performance\n", "# Determine the parameter dimension of the network\n",
" # One can change it to SGD or RMSprop.\n", "net = Net(shape=[THETA_SIZE])\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n",
"\n", "\n",
" # Optimization loop\n", "# We use Adam optimizer for better performance\n",
" for itr in range(1, ITR + 1):\n", "# One can change it to SGD or RMSprop.\n",
" \n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" # Forward propagation calculates the loss function and returns the estimated energy spectrum\n", "\n",
" loss, loss_components = net(hamiltonian, N)\n", "# Optimization loop\n",
" \n", "for itr in range(1, ITR + 1):\n",
" # Under the dynamic graph mechanism, use back propagation to minimize the loss function\n", "\n",
" loss.backward()\n", " # Forward propagation calculates the loss function and returns the estimated energy spectrum\n",
" opt.minimize(loss)\n", " loss, loss_components = net(hamiltonian, N)\n",
" net.clear_gradients()\n", "\n",
" \n", " # Under the dynamic graph mechanism, use back propagation to minimize the loss function\n",
" # Print training results\n", " loss.backward()\n",
" if itr% 10 == 0:\n", " opt.minimize(loss)\n",
" print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])" " opt.clear_grad()\n",
"\n",
" # Print training results\n",
" if itr% 10 == 0:\n",
" print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])"
] ]
}, },
{ {
...@@ -292,11 +299,11 @@ ...@@ -292,11 +299,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 9,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:46.288156Z", "end_time": "2021-03-09T03:41:43.152444Z",
"start_time": "2021-01-09T10:39:46.253447Z" "start_time": "2021-03-09T03:41:43.105409Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -304,14 +311,14 @@ ...@@ -304,14 +311,14 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"The estimated ground state energy is: [-3.73602114]\n", "The estimated ground state energy is: [-2.18762367]\n",
"The theoretical ground state energy: -3.753326573918093\n", "The theoretical ground state energy: -2.18790201165885\n",
"The estimated 1st excited state energy is: [-0.80121753]\n", "The estimated 1st excited state energy is: [-0.13721027]\n",
"The theoretical 1st excited state energy: -0.8299424429462511\n", "The theoretical 1st excited state energy: -0.13704127143749587\n",
"The estimated 2nd excited state energy is: [1.48536538]\n", "The estimated 2nd excited state energy is: [0.85251458]\n",
"The theoretical 2nd excited state energy: 1.5045893361511813\n", "The theoretical 2nd excited state energy: 0.8523274042087416\n",
"The estimated 3rd excited state energy is: [3.05187329]\n", "The estimated 3rd excited state energy is: [1.47231937]\n",
"The theoretical 3rd excited state energy: 3.078679680713162\n" "The theoretical 3rd excited state energy: 1.4726158788876045\n"
] ]
} }
], ],
...@@ -366,7 +373,7 @@ ...@@ -366,7 +373,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.0" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -115,11 +115,11 @@ ...@@ -115,11 +115,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:23.645493Z", "end_time": "2021-03-09T03:38:25.880887Z",
"start_time": "2021-01-09T07:44:20.439467Z" "start_time": "2021-03-09T03:38:23.112486Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -127,7 +127,6 @@ ...@@ -127,7 +127,6 @@
"import os\n", "import os\n",
"import platform\n", "import platform\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"%config InlineBackend.figure_format = 'svg'\n",
"from IPython.display import clear_output\n", "from IPython.display import clear_output\n",
"\n", "\n",
"import numpy\n", "import numpy\n",
...@@ -135,12 +134,10 @@ ...@@ -135,12 +134,10 @@
"from numpy import pi as PI\n", "from numpy import pi as PI\n",
"from numpy import savez, zeros\n", "from numpy import savez, zeros\n",
"\n", "\n",
"from paddle import fluid\n", "import paddle\n",
"from paddle.complex import matmul, transpose\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import pauli_str_to_matrix\n", "from paddle_quantum.utils import pauli_str_to_matrix\n",
"from paddle_quantum.VQE.chemistrysub import H2_generator\n", "from paddle_quantum.VQE.chemistrysub import H2_generator"
"clear_output()"
] ]
}, },
{ {
...@@ -152,11 +149,11 @@ ...@@ -152,11 +149,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:23.664668Z", "end_time": "2021-03-09T03:38:29.535703Z",
"start_time": "2021-01-09T07:44:23.649741Z" "start_time": "2021-03-09T03:38:29.530224Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -176,13 +173,13 @@ ...@@ -176,13 +173,13 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:25.822149Z", "end_time": "2021-03-09T03:36:14.021622Z",
"start_time": "2021-01-09T07:44:23.668727Z" "start_time": "2021-03-09T03:35:52.518925Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"!pip install openfermion==0.11.0\n", "!pip install openfermion\n",
"clear_output()" "clear_output()"
] ]
}, },
...@@ -191,13 +188,13 @@ ...@@ -191,13 +188,13 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:28.254506Z", "end_time": "2021-03-09T03:36:21.227368Z",
"start_time": "2021-01-09T07:44:25.828270Z" "start_time": "2021-03-09T03:36:14.028819Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"!pip install openfermionpyscf==0.4\n", "!pip install openfermionpyscf\n",
"clear_output()" "clear_output()"
] ]
}, },
...@@ -206,8 +203,8 @@ ...@@ -206,8 +203,8 @@
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:29.175345Z", "end_time": "2021-03-09T03:38:50.158332Z",
"start_time": "2021-01-09T07:44:28.259368Z" "start_time": "2021-03-09T03:38:47.301344Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -216,21 +213,21 @@ ...@@ -216,21 +213,21 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"The generated h2 Hamiltonian is \n", "The generated h2 Hamiltonian is \n",
" (-0.04207897647782281+0j) [] +\n", " -0.042078976477822494 [] +\n",
"(-0.04475014401535161+0j) [X0 X1 Y2 Y3] +\n", "-0.04475014401535163 [X0 X1 Y2 Y3] +\n",
"(0.04475014401535161+0j) [X0 Y1 Y2 X3] +\n", "0.04475014401535163 [X0 Y1 Y2 X3] +\n",
"(0.04475014401535161+0j) [Y0 X1 X2 Y3] +\n", "0.04475014401535163 [Y0 X1 X2 Y3] +\n",
"(-0.04475014401535161+0j) [Y0 Y1 X2 X3] +\n", "-0.04475014401535163 [Y0 Y1 X2 X3] +\n",
"(0.17771287465139946+0j) [Z0] +\n", "0.17771287465139946 [Z0] +\n",
"(0.17059738328801055+0j) [Z0 Z1] +\n", "0.17059738328801055 [Z0 Z1] +\n",
"(0.12293305056183798+0j) [Z0 Z2] +\n", "0.12293305056183797 [Z0 Z2] +\n",
"(0.16768319457718958+0j) [Z0 Z3] +\n", "0.1676831945771896 [Z0 Z3] +\n",
"(0.1777128746513994+0j) [Z1] +\n", "0.17771287465139946 [Z1] +\n",
"(0.16768319457718958+0j) [Z1 Z2] +\n", "0.1676831945771896 [Z1 Z2] +\n",
"(0.12293305056183798+0j) [Z1 Z3] +\n", "0.12293305056183797 [Z1 Z3] +\n",
"(-0.24274280513140456+0j) [Z2] +\n", "-0.24274280513140462 [Z2] +\n",
"(0.17627640804319586+0j) [Z2 Z3] +\n", "0.1762764080431959 [Z2 Z3] +\n",
"(-0.24274280513140456+0j) [Z3]\n" "-0.24274280513140462 [Z3]\n"
] ]
} }
], ],
...@@ -245,16 +242,15 @@ ...@@ -245,16 +242,15 @@
" import openfermionpyscf\n", " import openfermionpyscf\n",
"\n", "\n",
" # 请检查是否正确下载了 h2 的几何构型文件\n", " # 请检查是否正确下载了 h2 的几何构型文件\n",
" geo = 'h2.xyz'\n", " geometry = 'h2.xyz'\n",
" # geometry = [('H', (0.0, 0.0, 0.0)), ('H', (0.0, 0.0, 0.74))]\n",
" basis = 'sto-3g'\n",
" charge = 0\n", " charge = 0\n",
" multiplicity = 1\n", " multiplicity = 1\n",
"\n", "\n",
" # 生成哈密顿量\n", " # 生成哈密顿量\n",
" mol = openfermion.hamiltonians.MolecularData(geo, 'sto-3g', multiplicity, charge)\n", " molecular_hamiltonian = openfermionpyscf.generate_molecular_hamiltonian(geometry, basis, multiplicity, charge)\n",
" openfermionpyscf.run_pyscf(mol)\n", " qubit_op = openfermion.transforms.jordan_wigner(molecular_hamiltonian)\n",
" terms_molecular_hamiltonian = mol.get_molecular_hamiltonian()\n",
" fermionic_hamiltonian = openfermion.transforms.get_fermion_operator(terms_molecular_hamiltonian)\n",
" qubit_op = openfermion.transforms.jordan_wigner(fermionic_hamiltonian)\n",
"\n", "\n",
" # 打印结果\n", " # 打印结果\n",
" print(\"The generated h2 Hamiltonian is \\n\", qubit_op)" " print(\"The generated h2 Hamiltonian is \\n\", qubit_op)"
...@@ -274,8 +270,8 @@ ...@@ -274,8 +270,8 @@
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:29.292390Z", "end_time": "2021-03-09T03:38:51.614460Z",
"start_time": "2021-01-09T07:44:29.267116Z" "start_time": "2021-03-09T03:38:51.605394Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -330,8 +326,8 @@ ...@@ -330,8 +326,8 @@
"execution_count": 7, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:29.313859Z", "end_time": "2021-03-09T03:38:52.753996Z",
"start_time": "2021-01-09T07:44:29.300530Z" "start_time": "2021-03-09T03:38:52.746918Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -380,23 +376,24 @@ ...@@ -380,23 +376,24 @@
"execution_count": 8, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:29.352036Z", "end_time": "2021-03-09T03:38:53.511563Z",
"start_time": "2021-01-09T07:44:29.336102Z" "start_time": "2021-03-09T03:38:53.505570Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class StateNet(fluid.dygraph.Layer):\n", "class StateNet(paddle.nn.Layer):\n",
" \"\"\"\n", " \"\"\"\n",
" Construct the model net\n", " Construct the model net\n",
" \"\"\"\n", " \"\"\"\n",
"\n", "\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " def __init__(self, shape, dtype=\"float64\"):\n",
" low=0.0, high=2 * PI), dtype=\"float64\"):\n",
" super(StateNet, self).__init__()\n", " super(StateNet, self).__init__()\n",
" \n", " \n",
" # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n", " # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n",
" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.theta = self.create_parameter(shape=shape, \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # 定义损失函数和前向传播机制\n", " # 定义损失函数和前向传播机制\n",
" def forward(self, N, D):\n", " def forward(self, N, D):\n",
...@@ -421,14 +418,14 @@ ...@@ -421,14 +418,14 @@
"execution_count": 9, "execution_count": 9,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:29.362343Z", "end_time": "2021-03-09T03:38:54.477162Z",
"start_time": "2021-01-09T07:44:29.357578Z" "start_time": "2021-03-09T03:38:54.472259Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"ITR = 100 # 设置训练的总迭代次数\n", "ITR = 80 # 设置训练的总迭代次数\n",
"LR = 0.2 # 设置学习速率\n", "LR = 0.4 # 设置学习速率\n",
"D = 2 # 设置量子神经网络中重复计算模块的深度 Depth" "D = 2 # 设置量子神经网络中重复计算模块的深度 Depth"
] ]
}, },
...@@ -438,7 +435,7 @@ ...@@ -438,7 +435,7 @@
"source": [ "source": [
"### 进行训练\n", "### 进行训练\n",
"\n", "\n",
"当训练模型的各项参数都设置完成后,我们将数据转化为Paddle动态图中的变量,进而进行量子神经网络的训练。过程中我们用的是Adam Optimizer,也可以调用Paddle中提供的其他优化器。我们将训练过程中的结果存储在summary_data文件中。" "当训练模型的各项参数都设置完成后,我们将数据转化为 Paddle 中的张量,进而进行量子神经网络的训练。过程中我们用的是Adam Optimizer,也可以调用Paddle中提供的其他优化器。我们将训练过程中的结果存储在summary_data文件中。"
] ]
}, },
{ {
...@@ -446,8 +443,8 @@ ...@@ -446,8 +443,8 @@
"execution_count": 10, "execution_count": 10,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:49.755405Z", "end_time": "2021-03-09T03:39:12.114397Z",
"start_time": "2021-01-09T07:44:29.368768Z" "start_time": "2021-03-09T03:38:55.265261Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -455,60 +452,53 @@ ...@@ -455,60 +452,53 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 20 loss: -0.9230\n", "iter: 20 loss: -1.0791\n",
"iter: 20 Ground state energy: -0.9230 Ha\n", "iter: 20 Ground state energy: -1.0791 Ha\n",
"iter: 40 loss: -1.1241\n", "iter: 40 loss: -1.1288\n",
"iter: 40 Ground state energy: -1.1241 Ha\n", "iter: 40 Ground state energy: -1.1288 Ha\n",
"iter: 60 loss: -1.1332\n", "iter: 60 loss: -1.1353\n",
"iter: 60 Ground state energy: -1.1332 Ha\n", "iter: 60 Ground state energy: -1.1353 Ha\n",
"iter: 80 loss: -1.1359\n", "iter: 80 loss: -1.1361\n",
"iter: 80 Ground state energy: -1.1359 Ha\n", "iter: 80 Ground state energy: -1.1361 Ha\n"
"iter: 100 loss: -1.1362\n",
"iter: 100 Ground state energy: -1.1362 Ha\n"
] ]
} }
], ],
"source": [ "source": [
"# 初始化paddle动态图机制\n", "# 确定网络的参数维度\n",
"with fluid.dygraph.guard():\n", "net = StateNet(shape=[D + 1, N, 1])\n",
"\n", "\n",
"# 一般来说,我们利用Adam优化器来获得相对好的收敛,\n",
"# 当然你可以改成SGD或者是RMS prop.\n",
"opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"\n", "\n",
" # 确定网络的参数维度\n", "# 记录优化结果\n",
" net = StateNet(shape=[D + 1, N, 1])\n", "summary_iter, summary_loss = [], []\n",
"\n", "\n",
" # 一般来说,我们利用Adam优化器来获得相对好的收敛,\n", "# 优化循环\n",
" # 当然你可以改成SGD或者是RMS prop.\n", "for itr in range(1, ITR + 1):\n",
" opt = fluid.optimizer.AdamOptimizer(\n",
" learning_rate=LR, parameter_list=net.parameters())\n",
"\n", "\n",
" # 记录优化结果\n", " # 前向传播计算损失函数\n",
" summary_iter, summary_loss = [], []\n", " loss = net(N, D)\n",
" \n",
" # 优化循环\n",
" for itr in range(1, ITR + 1):\n",
" \n",
" # 前向传播计算损失函数\n",
" loss = net(N, D)\n",
"\n", "\n",
" # 在动态图机制下,反向传播极小化损失函数\n", " # 在动态图机制下,反向传播极小化损失函数\n",
" loss.backward()\n", " loss.backward()\n",
" opt.minimize(loss)\n", " opt.minimize(loss)\n",
" net.clear_gradients()\n", " opt.clear_grad()\n",
" \n", "\n",
" # 更新优化结果\n", " # 更新优化结果\n",
" summary_loss.append(loss.numpy())\n", " summary_loss.append(loss.numpy())\n",
" summary_iter.append(itr)\n", " summary_iter.append(itr)\n",
" \n", "\n",
" # 打印结果\n", " # 打印结果\n",
" if itr % 20 == 0:\n", " if itr % 20 == 0:\n",
" print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n", " print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n",
" print(\"iter:\", itr, \"Ground state energy:\", \"%.4f Ha\" \n", " print(\"iter:\", itr, \"Ground state energy:\", \"%.4f Ha\" \n",
" % loss.numpy())\n", " % loss.numpy())\n",
"\n", "\n",
" # 储存训练结果到 output 文件夹\n", "# 储存训练结果到 output 文件夹\n",
" os.makedirs(\"output\", exist_ok=True)\n", "os.makedirs(\"output\", exist_ok=True)\n",
" savez(\"./output/summary_data\", iter = summary_iter, \n", "savez(\"./output/summary_data\", iter = summary_iter, \n",
" energy=summary_loss)" " energy=summary_loss)"
] ]
}, },
{ {
...@@ -524,1324 +514,14 @@ ...@@ -524,1324 +514,14 @@
"execution_count": 11, "execution_count": 11,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:44:50.689035Z", "end_time": "2021-03-09T03:39:15.991207Z",
"start_time": "2021-01-09T07:44:49.759395Z" "start_time": "2021-03-09T03:39:14.982817Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/svg+xml": [ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAEGCAYAAAB7DNKzAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAxA0lEQVR4nO3deXxU1fnH8c/DEhBkBxEBBRRkJ0pAaV2QRdwBl6rVClq1ta6tdXu1/f1obX9uta1Vi/vW2qKloiK4FJSK2qoB2RdRwBJFQMIOAUKe3x/nJkzCZEgIyR2S7/v1uq+529z7ZGYyz5xz7j3H3B0REZHS1Io7ABERSW9KFCIikpIShYiIpKREISIiKSlRiIhISnXiDmB/a9mypXfo0CHuMEREDigzZsz4xt1bJdtW7RJFhw4dyM7OjjsMEZEDipl9Udo2VT2JiEhKShQiIpKSEoWIiKRU7dooRGqqnTt3kpOTQ15eXtyhSBqrX78+7dq1o27dumV+jhKFSDWRk5NDo0aN6NChA2YWdziShtydtWvXkpOTQ8eOHcv8PFU9iVQTeXl5tGjRQklCSmVmtGjRotylTiUKkWpESUL2Zl8+I0oUhbZtg+efh8WL445ERCStKFEU2rkTxo2DTz+NOxIRkbSiRFGoXr3wuH17vHGIiKQZJYpCGRnhcceOeOMQqQYGDRpEfn5+yn22bdvGySefzK5duwDYtWsXN954Iz169KBXr14sXbqUHTt2cNJJJxU71sCBA1m+fDkAjz76KNdcc02x4/bs2ZOFCxfuse/+jmXdunWMHDmyTK/HgU6JopBZSBYqUYhUyPz582nRogV16qS++v6pp57i3HPPpXbt2gDcdddddOrUifnz53PDDTfwpz/9iYyMDAYPHswLL7yQ9Bhz587l2GOPLVrOy8tj+fLldOnSpVwx70sszZo1Izc3l7Vr15brXAci3UeRKCNDJQqpHh5/HJYu3b/H7NQJrrpqr7u98sorjBgxAoBjjjmG119/nYceeoijjjqKjh07MnbsWMaNG8fzzz/PX//6VwC2bNnChAkTmDFjBgAdO3Zk0qRJAIwYMYI77riDSy65ZI9zzZkzh8svv7xoee7cuXTp0qXoCz9RZcRy5plnMnHiREaPHl2WV/CApUSRqF49lShEKmjy5Mm89tpr5Ofnk5uby6GHHsrs2bM5//zzeffdd+nTpw87duxg6dKlFA4JMGXKFFasWEFmZiYAubm5DBkyBAhVSR9//HHSc82fP59zzz236JLPzZs3c9ZZZ+2xX2XFMnz4cG677TYlihpFVU9SXZThl39l2Lp1Kzt27KBp06bMmzePrl27ArBgwQK6d+/Ogw8+yLnnnss333xD06ZNi543a9YsfvWrX/HDH/4QgCuvvJLevXsDULt2bTIyMti0aRONGjUqes6KFSto1aoVixYtKlp33XXXJb3jeNGiRZUSy9FHH83iGnBJvdooEqlEIVIhDRo0wMzYvHkzixcv5uijjyY3N5eDDz6YjIwMsrOz6devHwcddFCxu4PXrVtHgwYNgPDr/6233uLss88u2r59+3bq169f7Fxz586lR48exdYtWLCg6Es9UWXF8sUXX5SrK4wDlRJFonr11EYhUkHDhg3jjTfeICMjg0WLFpGdnU2fPn34y1/+QocOHTjkkENo1qwZu3btKvqC7tKlC//5z38A+P3vf8+ZZ55Z9AW8du1aWrZsuUcndnPmzKF79+7F1s2fP59evXrtEVNlxfLKK68wfPjw/fXSpS0likSqehKpsOHDh/Pyyy9z2mmn0bVrVy655BKmTZtGdnY2zz33XNF+p556Ku+99x4AF198MTNnzuSoo45izpw5/O53vyva75133uHMM8/c4zxz584tlihyc3Nxdw499NA99q2sWCZOnFgjEgXuXq2mvn37+j4bM8b9ppv2/fkiMVqwYEHcIRTp1auX79y5093dR48e7W+99dYe+8yYMcMvvfTSvR5r5MiRvnjx4qLlk08+2ZctW1amOEruuz9jyc3N9RNPPLFMcaSbZJ8VINtL+V6NtURhZqeZ2WIz+8zMbk+yvZ6ZvRBt/9DMOlRqQCpRiOwXc+bMKbqPYs6cOUnbDY499lhOOeWUopvcktmxYwcjRowo930RqeLaX7E0a9aMd999d7/Ele5iu+rJzGoDDwNDgRzgYzN71d0XJOz2fWCdux9lZhcB9wAXVlpQaswW2e8K70dI5oorrkj53IyMDC677LJi60aPHl3sKqVUSu67v2OpKeIsUfQHPnP3pe6+AxgHlKzsGw48G82PBwZbZfajrMZskbRXkUQh+ybORNEWWJGwnBOtS7qPu+cDG4AWlRaRShQiInuoFlc9mdnVZpZtZtlr1qzZ9wOpCw8RkT3EmSi+BNonLLeL1iXdx8zqAE2APXrgcvfH3D3L3bNatWq17xFlZMCuXbCXXi9FRGqSOBPFx0BnM+toZhnARcCrJfZ5FRgVzZ8PvB1dxlU5CsekUKlCRKRIbFc9uXu+mV0HvAnUBp5y9/lm9ivC9byvAk8Cfzazz4BcQjKpPImDF0W38IuI1HSxtlG4+2R37+LuR7r7b6J1/xMlCdw9z90vcPej3L2/u+/nfpNLUIlCpEJWrVrFd7/7XTp16kTfvn0ZMGAAEyZMqNIYli9fTs+ePcu8/7Rp0/jggw/2237VUbVozN5vNMqdyD5zd0aMGMFJJ53E0qVLmTFjBuPGjSMnJ2ePffc2+l1VOhATRVW/fkoUiQpLFAk9SYpI2bz99ttkZGQUdc8NcMQRR3D99dcD8Mwzz3DOOecwaNAgBg8eTG5uLiNGjKB3794cf/zxzJkzB4AxY8bw29/+tugYPXv2ZPny5Sxfvpxu3bpx1VVX0aNHD0499VS2bdsGhBvp+vTpQ58+fXj44YdLjfGPf/wj3bt3p3fv3lx00UUsX76cRx55hN///vdkZmYyffp0Jk6cyHHHHccxxxzDkCFDWLVqVdL91qxZw3nnnUe/fv3o168f77///h7n27VrF7fccgv9+vWjd+/ePProo0BIOgMHDuT8888v6oOqsPl1xowZnHzyyfTt25dhw4axcuVKIAzretNNN5GVlcUDDzzAxx9/TO/evcnMzOSWW24pKkWddNJJzJo1qyiGE044gdmzZ5f7/SymtL49DtSpQn09ffKJ+1lnuc+bt+/HEIlJyf57br/dfcqUML9zZ1h+++2wnJcXlt99Nyxv3hyW338/LG/YEJY//DAs5+bu/fwPPPCA35Sir7Snn37a27Zt62vXrnV39+uuu87HjBnj7u5Tp071Pn36uLv7//7v//p9991X9LwePXr4smXLfNmyZV67dm3/5JNP3N39ggsu8D//+c/uHvqW+te//uXu7j/96U+9R48eSWNo06aN5+Xlubv7unXrkp4vNzfXCwoK3N398ccf95/85CdJ97v44ot9+vTp7u7+xRdfeNeuXfc436OPPup33nmnu7vn5eV53759fenSpf7OO+9448aNfcWKFb5r1y4//vjjffr06b5jxw4fMGCAr1692t3dx40b55dffrm7h36rrrnmmmKvywcffODu7rfddlvR3/zMM8/4jTfe6O7uixcv9mTfieXt60kDFyVKbMwWkQq59tpree+998jIyCgaFW7o0KE0b94cgPfee49//OMfAAwaNIi1a9eycePGlMfs2LFj0chzffv2Zfny5axfv57169dz0kknAfC9732P119/Penze/fuzSWXXMKIESOKhmstKScnhwsvvJCVK1eyY8eOUsebmDJlCgsW7O5xaOPGjWzevJmDDz64aN1bb73FnDlzGD9+PAAbNmxgyZIlZGRk0L9/f9q1awdAZmYmy5cvLxrwaejQoUAokbRp06boeBdeGHowWr9+PZs2bWLAgAEAfPe73+W1114D4IILLuDOO+/kvvvu46mnntovo+8pUSRSY7ZUI3fdtXu+Tp3iy/XqFV9u2LD4cuPGxZebNdv7+Xr06FH0xQ/w8MMP880335CVlZVwnoZ7PU6dOnUoKCgoWk4cVKhe4f8oYbS5wqqn0lx++eV88sknHHbYYUyePJlJkybx7rvvMnHiRH7zm98wd+7cPZ5z/fXX85Of/IRzzjmHadOmMWbMmKTHLigo4D//+c8eAyolcncefPBBhg0bVmz9tGnT9vhb8vPzcXd69OjBv//976THK8vr16BBA4YOHcorr7zCiy++mLJ/q7JSG0WiwsZslShEym3QoEHk5eUxduzYonVbt24tdf8TTzyR559/HghfnC1btqRx48Z06NCBmTNnAjBz5kyWLVuW8rxNmzaladOmReNJFB4T4Omnn2bWrFlMnjyZgoICVqxYwSmnnMI999zDhg0b2Lx5M40aNWLTpk1Fz9mwYQNt24behJ599tmi9SX3O/XUU3nwwQeLlhPbBQoNGzaMsWPHsnPnTgA+/fRTtmzZUurfcvTRR7NmzZqiRLFz507mz5+f9G9u1KgRH374IQDjxo0rtv3KK6/khhtuoF+/fjQrS5bfCyWKRCpRiOwzM+Pll1/mX//6Fx07dqR///6MGjWKe+65J+n+Y8aMYcaMGfTu3Zvbb7+96Ev5vPPOIzc3lx49evDQQw+VqYvxp59+mmuvvZbMzMyiRuGSdu3axaWXXkqvXr045phjuOGGG2jatClnn302EyZMKGqkHjNmDBdccAF9+/alZcuWRc8vud8f//hHsrOz6d27N927d+eRRx7Z45xXXnkl3bt359hjj6Vnz5784Ac/SHnFUkZGBuPHj+e2226jT58+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\n",
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Created with matplotlib (https://matplotlib.org/) -->\n",
"<svg height=\"262.19625pt\" version=\"1.1\" viewBox=\"0 0 394.160937 262.19625\" width=\"394.160937pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
" <metadata>\n",
" <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
" <cc:Work>\n",
" <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
" <dc:date>2021-01-09T15:44:50.491460</dc:date>\n",
" <dc:format>image/svg+xml</dc:format>\n",
" <dc:creator>\n",
" <cc:Agent>\n",
" <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\n",
" </cc:Agent>\n",
" </dc:creator>\n",
" </cc:Work>\n",
" </rdf:RDF>\n",
" </metadata>\n",
" <defs>\n",
" <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n",
" </defs>\n",
" <g id=\"figure_1\">\n",
" <g id=\"patch_1\">\n",
" <path d=\"M 0 262.19625 \n",
"L 394.160937 262.19625 \n",
"L 394.160937 0 \n",
"L 0 0 \n",
"z\n",
"\" style=\"fill:none;\"/>\n",
" </g>\n",
" <g id=\"axes_1\">\n",
" <g id=\"patch_2\">\n",
" <path d=\"M 52.160938 224.64 \n",
"L 386.960938 224.64 \n",
"L 386.960938 7.2 \n",
"L 52.160938 7.2 \n",
"z\n",
"\" style=\"fill:#ffffff;\"/>\n",
" </g>\n",
" <g id=\"matplotlib.axis_1\">\n",
" <g id=\"xtick_1\">\n",
" <g id=\"line2d_1\">\n",
" <defs>\n",
" <path d=\"M 0 0 \n",
"L 0 3.5 \n",
"\" id=\"m158c43600d\" style=\"stroke:#000000;stroke-width:0.8;\"/>\n",
" </defs>\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"64.304739\" xlink:href=\"#m158c43600d\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_1\">\n",
" <!-- 0 -->\n",
" <g transform=\"translate(61.123489 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 31.78125 66.40625 \n",
"Q 24.171875 66.40625 20.328125 58.90625 \n",
"Q 16.5 51.421875 16.5 36.375 \n",
"Q 16.5 21.390625 20.328125 13.890625 \n",
"Q 24.171875 6.390625 31.78125 6.390625 \n",
"Q 39.453125 6.390625 43.28125 13.890625 \n",
"Q 47.125 21.390625 47.125 36.375 \n",
"Q 47.125 51.421875 43.28125 58.90625 \n",
"Q 39.453125 66.40625 31.78125 66.40625 \n",
"z\n",
"M 31.78125 74.21875 \n",
"Q 44.046875 74.21875 50.515625 64.515625 \n",
"Q 56.984375 54.828125 56.984375 36.375 \n",
"Q 56.984375 17.96875 50.515625 8.265625 \n",
"Q 44.046875 -1.421875 31.78125 -1.421875 \n",
"Q 19.53125 -1.421875 13.0625 8.265625 \n",
"Q 6.59375 17.96875 6.59375 36.375 \n",
"Q 6.59375 54.828125 13.0625 64.515625 \n",
"Q 19.53125 74.21875 31.78125 74.21875 \n",
"z\n",
"\" id=\"DejaVuSans-48\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_2\">\n",
" <g id=\"line2d_2\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"125.792342\" xlink:href=\"#m158c43600d\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_2\">\n",
" <!-- 20 -->\n",
" <g transform=\"translate(119.429842 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 19.1875 8.296875 \n",
"L 53.609375 8.296875 \n",
"L 53.609375 0 \n",
"L 7.328125 0 \n",
"L 7.328125 8.296875 \n",
"Q 12.9375 14.109375 22.625 23.890625 \n",
"Q 32.328125 33.6875 34.8125 36.53125 \n",
"Q 39.546875 41.84375 41.421875 45.53125 \n",
"Q 43.3125 49.21875 43.3125 52.78125 \n",
"Q 43.3125 58.59375 39.234375 62.25 \n",
"Q 35.15625 65.921875 28.609375 65.921875 \n",
"Q 23.96875 65.921875 18.8125 64.3125 \n",
"Q 13.671875 62.703125 7.8125 59.421875 \n",
"L 7.8125 69.390625 \n",
"Q 13.765625 71.78125 18.9375 73 \n",
"Q 24.125 74.21875 28.421875 74.21875 \n",
"Q 39.75 74.21875 46.484375 68.546875 \n",
"Q 53.21875 62.890625 53.21875 53.421875 \n",
"Q 53.21875 48.921875 51.53125 44.890625 \n",
"Q 49.859375 40.875 45.40625 35.40625 \n",
"Q 44.1875 33.984375 37.640625 27.21875 \n",
"Q 31.109375 20.453125 19.1875 8.296875 \n",
"z\n",
"\" id=\"DejaVuSans-50\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-50\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_3\">\n",
" <g id=\"line2d_3\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"187.279946\" xlink:href=\"#m158c43600d\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_3\">\n",
" <!-- 40 -->\n",
" <g transform=\"translate(180.917446 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 37.796875 64.3125 \n",
"L 12.890625 25.390625 \n",
"L 37.796875 25.390625 \n",
"z\n",
"M 35.203125 72.90625 \n",
"L 47.609375 72.90625 \n",
"L 47.609375 25.390625 \n",
"L 58.015625 25.390625 \n",
"L 58.015625 17.1875 \n",
"L 47.609375 17.1875 \n",
"L 47.609375 0 \n",
"L 37.796875 0 \n",
"L 37.796875 17.1875 \n",
"L 4.890625 17.1875 \n",
"L 4.890625 26.703125 \n",
"z\n",
"\" id=\"DejaVuSans-52\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-52\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_4\">\n",
" <g id=\"line2d_4\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"248.767549\" xlink:href=\"#m158c43600d\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_4\">\n",
" <!-- 60 -->\n",
" <g transform=\"translate(242.405049 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 33.015625 40.375 \n",
"Q 26.375 40.375 22.484375 35.828125 \n",
"Q 18.609375 31.296875 18.609375 23.390625 \n",
"Q 18.609375 15.53125 22.484375 10.953125 \n",
"Q 26.375 6.390625 33.015625 6.390625 \n",
"Q 39.65625 6.390625 43.53125 10.953125 \n",
"Q 47.40625 15.53125 47.40625 23.390625 \n",
"Q 47.40625 31.296875 43.53125 35.828125 \n",
"Q 39.65625 40.375 33.015625 40.375 \n",
"z\n",
"M 52.59375 71.296875 \n",
"L 52.59375 62.3125 \n",
"Q 48.875 64.0625 45.09375 64.984375 \n",
"Q 41.3125 65.921875 37.59375 65.921875 \n",
"Q 27.828125 65.921875 22.671875 59.328125 \n",
"Q 17.53125 52.734375 16.796875 39.40625 \n",
"Q 19.671875 43.65625 24.015625 45.921875 \n",
"Q 28.375 48.1875 33.59375 48.1875 \n",
"Q 44.578125 48.1875 50.953125 41.515625 \n",
"Q 57.328125 34.859375 57.328125 23.390625 \n",
"Q 57.328125 12.15625 50.6875 5.359375 \n",
"Q 44.046875 -1.421875 33.015625 -1.421875 \n",
"Q 20.359375 -1.421875 13.671875 8.265625 \n",
"Q 6.984375 17.96875 6.984375 36.375 \n",
"Q 6.984375 53.65625 15.1875 63.9375 \n",
"Q 23.390625 74.21875 37.203125 74.21875 \n",
"Q 40.921875 74.21875 44.703125 73.484375 \n",
"Q 48.484375 72.75 52.59375 71.296875 \n",
"z\n",
"\" id=\"DejaVuSans-54\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-54\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_5\">\n",
" <g id=\"line2d_5\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"310.255152\" xlink:href=\"#m158c43600d\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_5\">\n",
" <!-- 80 -->\n",
" <g transform=\"translate(303.892652 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 31.78125 34.625 \n",
"Q 24.75 34.625 20.71875 30.859375 \n",
"Q 16.703125 27.09375 16.703125 20.515625 \n",
"Q 16.703125 13.921875 20.71875 10.15625 \n",
"Q 24.75 6.390625 31.78125 6.390625 \n",
"Q 38.8125 6.390625 42.859375 10.171875 \n",
"Q 46.921875 13.96875 46.921875 20.515625 \n",
"Q 46.921875 27.09375 42.890625 30.859375 \n",
"Q 38.875 34.625 31.78125 34.625 \n",
"z\n",
"M 21.921875 38.8125 \n",
"Q 15.578125 40.375 12.03125 44.71875 \n",
"Q 8.5 49.078125 8.5 55.328125 \n",
"Q 8.5 64.0625 14.71875 69.140625 \n",
"Q 20.953125 74.21875 31.78125 74.21875 \n",
"Q 42.671875 74.21875 48.875 69.140625 \n",
"Q 55.078125 64.0625 55.078125 55.328125 \n",
"Q 55.078125 49.078125 51.53125 44.71875 \n",
"Q 48 40.375 41.703125 38.8125 \n",
"Q 48.828125 37.15625 52.796875 32.3125 \n",
"Q 56.78125 27.484375 56.78125 20.515625 \n",
"Q 56.78125 9.90625 50.3125 4.234375 \n",
"Q 43.84375 -1.421875 31.78125 -1.421875 \n",
"Q 19.734375 -1.421875 13.25 4.234375 \n",
"Q 6.78125 9.90625 6.78125 20.515625 \n",
"Q 6.78125 27.484375 10.78125 32.3125 \n",
"Q 14.796875 37.15625 21.921875 38.8125 \n",
"z\n",
"M 18.3125 54.390625 \n",
"Q 18.3125 48.734375 21.84375 45.5625 \n",
"Q 25.390625 42.390625 31.78125 42.390625 \n",
"Q 38.140625 42.390625 41.71875 45.5625 \n",
"Q 45.3125 48.734375 45.3125 54.390625 \n",
"Q 45.3125 60.0625 41.71875 63.234375 \n",
"Q 38.140625 66.40625 31.78125 66.40625 \n",
"Q 25.390625 66.40625 21.84375 63.234375 \n",
"Q 18.3125 60.0625 18.3125 54.390625 \n",
"z\n",
"\" id=\"DejaVuSans-56\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-56\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_6\">\n",
" <g id=\"line2d_6\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"371.742756\" xlink:href=\"#m158c43600d\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_6\">\n",
" <!-- 100 -->\n",
" <g transform=\"translate(362.199006 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 12.40625 8.296875 \n",
"L 28.515625 8.296875 \n",
"L 28.515625 63.921875 \n",
"L 10.984375 60.40625 \n",
"L 10.984375 69.390625 \n",
"L 28.421875 72.90625 \n",
"L 38.28125 72.90625 \n",
"L 38.28125 8.296875 \n",
"L 54.390625 8.296875 \n",
"L 54.390625 0 \n",
"L 12.40625 0 \n",
"z\n",
"\" id=\"DejaVuSans-49\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_7\">\n",
" <!-- Number of iteration -->\n",
" <g transform=\"translate(170.354688 252.916562)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 9.8125 72.90625 \n",
"L 23.09375 72.90625 \n",
"L 55.421875 11.921875 \n",
"L 55.421875 72.90625 \n",
"L 64.984375 72.90625 \n",
"L 64.984375 0 \n",
"L 51.703125 0 \n",
"L 19.390625 60.984375 \n",
"L 19.390625 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-78\"/>\n",
" <path d=\"M 8.5 21.578125 \n",
"L 8.5 54.6875 \n",
"L 17.484375 54.6875 \n",
"L 17.484375 21.921875 \n",
"Q 17.484375 14.15625 20.5 10.265625 \n",
"Q 23.53125 6.390625 29.59375 6.390625 \n",
"Q 36.859375 6.390625 41.078125 11.03125 \n",
"Q 45.3125 15.671875 45.3125 23.6875 \n",
"L 45.3125 54.6875 \n",
"L 54.296875 54.6875 \n",
"L 54.296875 0 \n",
"L 45.3125 0 \n",
"L 45.3125 8.40625 \n",
"Q 42.046875 3.421875 37.71875 1 \n",
"Q 33.40625 -1.421875 27.6875 -1.421875 \n",
"Q 18.265625 -1.421875 13.375 4.4375 \n",
"Q 8.5 10.296875 8.5 21.578125 \n",
"z\n",
"M 31.109375 56 \n",
"z\n",
"\" id=\"DejaVuSans-117\"/>\n",
" <path d=\"M 52 44.1875 \n",
"Q 55.375 50.25 60.0625 53.125 \n",
"Q 64.75 56 71.09375 56 \n",
"Q 79.640625 56 84.28125 50.015625 \n",
"Q 88.921875 44.046875 88.921875 33.015625 \n",
"L 88.921875 0 \n",
"L 79.890625 0 \n",
"L 79.890625 32.71875 \n",
"Q 79.890625 40.578125 77.09375 44.375 \n",
"Q 74.3125 48.1875 68.609375 48.1875 \n",
"Q 61.625 48.1875 57.5625 43.546875 \n",
"Q 53.515625 38.921875 53.515625 30.90625 \n",
"L 53.515625 0 \n",
"L 44.484375 0 \n",
"L 44.484375 32.71875 \n",
"Q 44.484375 40.625 41.703125 44.40625 \n",
"Q 38.921875 48.1875 33.109375 48.1875 \n",
"Q 26.21875 48.1875 22.15625 43.53125 \n",
"Q 18.109375 38.875 18.109375 30.90625 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 54.6875 \n",
"L 18.109375 54.6875 \n",
"L 18.109375 46.1875 \n",
"Q 21.1875 51.21875 25.484375 53.609375 \n",
"Q 29.78125 56 35.6875 56 \n",
"Q 41.65625 56 45.828125 52.96875 \n",
"Q 50 49.953125 52 44.1875 \n",
"z\n",
"\" id=\"DejaVuSans-109\"/>\n",
" <path d=\"M 48.6875 27.296875 \n",
"Q 48.6875 37.203125 44.609375 42.84375 \n",
"Q 40.53125 48.484375 33.40625 48.484375 \n",
"Q 26.265625 48.484375 22.1875 42.84375 \n",
"Q 18.109375 37.203125 18.109375 27.296875 \n",
"Q 18.109375 17.390625 22.1875 11.75 \n",
"Q 26.265625 6.109375 33.40625 6.109375 \n",
"Q 40.53125 6.109375 44.609375 11.75 \n",
"Q 48.6875 17.390625 48.6875 27.296875 \n",
"z\n",
"M 18.109375 46.390625 \n",
"Q 20.953125 51.265625 25.265625 53.625 \n",
"Q 29.59375 56 35.59375 56 \n",
"Q 45.5625 56 51.78125 48.09375 \n",
"Q 58.015625 40.1875 58.015625 27.296875 \n",
"Q 58.015625 14.40625 51.78125 6.484375 \n",
"Q 45.5625 -1.421875 35.59375 -1.421875 \n",
"Q 29.59375 -1.421875 25.265625 0.953125 \n",
"Q 20.953125 3.328125 18.109375 8.203125 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 75.984375 \n",
"L 18.109375 75.984375 \n",
"z\n",
"\" id=\"DejaVuSans-98\"/>\n",
" <path d=\"M 56.203125 29.59375 \n",
"L 56.203125 25.203125 \n",
"L 14.890625 25.203125 \n",
"Q 15.484375 15.921875 20.484375 11.0625 \n",
"Q 25.484375 6.203125 34.421875 6.203125 \n",
"Q 39.59375 6.203125 44.453125 7.46875 \n",
"Q 49.3125 8.734375 54.109375 11.28125 \n",
"L 54.109375 2.78125 \n",
"Q 49.265625 0.734375 44.1875 -0.34375 \n",
"Q 39.109375 -1.421875 33.890625 -1.421875 \n",
"Q 20.796875 -1.421875 13.15625 6.1875 \n",
"Q 5.515625 13.8125 5.515625 26.8125 \n",
"Q 5.515625 40.234375 12.765625 48.109375 \n",
"Q 20.015625 56 32.328125 56 \n",
"Q 43.359375 56 49.78125 48.890625 \n",
"Q 56.203125 41.796875 56.203125 29.59375 \n",
"z\n",
"M 47.21875 32.234375 \n",
"Q 47.125 39.59375 43.09375 43.984375 \n",
"Q 39.0625 48.390625 32.421875 48.390625 \n",
"Q 24.90625 48.390625 20.390625 44.140625 \n",
"Q 15.875 39.890625 15.1875 32.171875 \n",
"z\n",
"\" id=\"DejaVuSans-101\"/>\n",
" <path d=\"M 41.109375 46.296875 \n",
"Q 39.59375 47.171875 37.8125 47.578125 \n",
"Q 36.03125 48 33.890625 48 \n",
"Q 26.265625 48 22.1875 43.046875 \n",
"Q 18.109375 38.09375 18.109375 28.8125 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 54.6875 \n",
"L 18.109375 54.6875 \n",
"L 18.109375 46.1875 \n",
"Q 20.953125 51.171875 25.484375 53.578125 \n",
"Q 30.03125 56 36.53125 56 \n",
"Q 37.453125 56 38.578125 55.875 \n",
"Q 39.703125 55.765625 41.0625 55.515625 \n",
"z\n",
"\" id=\"DejaVuSans-114\"/>\n",
" <path id=\"DejaVuSans-32\"/>\n",
" <path d=\"M 30.609375 48.390625 \n",
"Q 23.390625 48.390625 19.1875 42.75 \n",
"Q 14.984375 37.109375 14.984375 27.296875 \n",
"Q 14.984375 17.484375 19.15625 11.84375 \n",
"Q 23.34375 6.203125 30.609375 6.203125 \n",
"Q 37.796875 6.203125 41.984375 11.859375 \n",
"Q 46.1875 17.53125 46.1875 27.296875 \n",
"Q 46.1875 37.015625 41.984375 42.703125 \n",
"Q 37.796875 48.390625 30.609375 48.390625 \n",
"z\n",
"M 30.609375 56 \n",
"Q 42.328125 56 49.015625 48.375 \n",
"Q 55.71875 40.765625 55.71875 27.296875 \n",
"Q 55.71875 13.875 49.015625 6.21875 \n",
"Q 42.328125 -1.421875 30.609375 -1.421875 \n",
"Q 18.84375 -1.421875 12.171875 6.21875 \n",
"Q 5.515625 13.875 5.515625 27.296875 \n",
"Q 5.515625 40.765625 12.171875 48.375 \n",
"Q 18.84375 56 30.609375 56 \n",
"z\n",
"\" id=\"DejaVuSans-111\"/>\n",
" <path d=\"M 37.109375 75.984375 \n",
"L 37.109375 68.5 \n",
"L 28.515625 68.5 \n",
"Q 23.6875 68.5 21.796875 66.546875 \n",
"Q 19.921875 64.59375 19.921875 59.515625 \n",
"L 19.921875 54.6875 \n",
"L 34.71875 54.6875 \n",
"L 34.71875 47.703125 \n",
"L 19.921875 47.703125 \n",
"L 19.921875 0 \n",
"L 10.890625 0 \n",
"L 10.890625 47.703125 \n",
"L 2.296875 47.703125 \n",
"L 2.296875 54.6875 \n",
"L 10.890625 54.6875 \n",
"L 10.890625 58.5 \n",
"Q 10.890625 67.625 15.140625 71.796875 \n",
"Q 19.390625 75.984375 28.609375 75.984375 \n",
"z\n",
"\" id=\"DejaVuSans-102\"/>\n",
" <path d=\"M 9.421875 54.6875 \n",
"L 18.40625 54.6875 \n",
"L 18.40625 0 \n",
"L 9.421875 0 \n",
"z\n",
"M 9.421875 75.984375 \n",
"L 18.40625 75.984375 \n",
"L 18.40625 64.59375 \n",
"L 9.421875 64.59375 \n",
"z\n",
"\" id=\"DejaVuSans-105\"/>\n",
" <path d=\"M 18.3125 70.21875 \n",
"L 18.3125 54.6875 \n",
"L 36.8125 54.6875 \n",
"L 36.8125 47.703125 \n",
"L 18.3125 47.703125 \n",
"L 18.3125 18.015625 \n",
"Q 18.3125 11.328125 20.140625 9.421875 \n",
"Q 21.96875 7.515625 27.59375 7.515625 \n",
"L 36.8125 7.515625 \n",
"L 36.8125 0 \n",
"L 27.59375 0 \n",
"Q 17.1875 0 13.234375 3.875 \n",
"Q 9.28125 7.765625 9.28125 18.015625 \n",
"L 9.28125 47.703125 \n",
"L 2.6875 47.703125 \n",
"L 2.6875 54.6875 \n",
"L 9.28125 54.6875 \n",
"L 9.28125 70.21875 \n",
"z\n",
"\" id=\"DejaVuSans-116\"/>\n",
" <path d=\"M 34.28125 27.484375 \n",
"Q 23.390625 27.484375 19.1875 25 \n",
"Q 14.984375 22.515625 14.984375 16.5 \n",
"Q 14.984375 11.71875 18.140625 8.90625 \n",
"Q 21.296875 6.109375 26.703125 6.109375 \n",
"Q 34.1875 6.109375 38.703125 11.40625 \n",
"Q 43.21875 16.703125 43.21875 25.484375 \n",
"L 43.21875 27.484375 \n",
"z\n",
"M 52.203125 31.203125 \n",
"L 52.203125 0 \n",
"L 43.21875 0 \n",
"L 43.21875 8.296875 \n",
"Q 40.140625 3.328125 35.546875 0.953125 \n",
"Q 30.953125 -1.421875 24.3125 -1.421875 \n",
"Q 15.921875 -1.421875 10.953125 3.296875 \n",
"Q 6 8.015625 6 15.921875 \n",
"Q 6 25.140625 12.171875 29.828125 \n",
"Q 18.359375 34.515625 30.609375 34.515625 \n",
"L 43.21875 34.515625 \n",
"L 43.21875 35.40625 \n",
"Q 43.21875 41.609375 39.140625 45 \n",
"Q 35.0625 48.390625 27.6875 48.390625 \n",
"Q 23 48.390625 18.546875 47.265625 \n",
"Q 14.109375 46.140625 10.015625 43.890625 \n",
"L 10.015625 52.203125 \n",
"Q 14.9375 54.109375 19.578125 55.046875 \n",
"Q 24.21875 56 28.609375 56 \n",
"Q 40.484375 56 46.34375 49.84375 \n",
"Q 52.203125 43.703125 52.203125 31.203125 \n",
"z\n",
"\" id=\"DejaVuSans-97\"/>\n",
" <path d=\"M 54.890625 33.015625 \n",
"L 54.890625 0 \n",
"L 45.90625 0 \n",
"L 45.90625 32.71875 \n",
"Q 45.90625 40.484375 42.875 44.328125 \n",
"Q 39.84375 48.1875 33.796875 48.1875 \n",
"Q 26.515625 48.1875 22.3125 43.546875 \n",
"Q 18.109375 38.921875 18.109375 30.90625 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 54.6875 \n",
"L 18.109375 54.6875 \n",
"L 18.109375 46.1875 \n",
"Q 21.34375 51.125 25.703125 53.5625 \n",
"Q 30.078125 56 35.796875 56 \n",
"Q 45.21875 56 50.046875 50.171875 \n",
"Q 54.890625 44.34375 54.890625 33.015625 \n",
"z\n",
"\" id=\"DejaVuSans-110\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-78\"/>\n",
" <use x=\"74.804688\" xlink:href=\"#DejaVuSans-117\"/>\n",
" <use x=\"138.183594\" xlink:href=\"#DejaVuSans-109\"/>\n",
" <use x=\"235.595703\" xlink:href=\"#DejaVuSans-98\"/>\n",
" <use x=\"299.072266\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"360.595703\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"401.708984\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"433.496094\" xlink:href=\"#DejaVuSans-111\"/>\n",
" <use x=\"494.677734\" xlink:href=\"#DejaVuSans-102\"/>\n",
" <use x=\"529.882812\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"561.669922\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"589.453125\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"628.662109\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"690.185547\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"731.298828\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"792.578125\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"831.787109\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"859.570312\" xlink:href=\"#DejaVuSans-111\"/>\n",
" <use x=\"920.751953\" xlink:href=\"#DejaVuSans-110\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"matplotlib.axis_2\">\n",
" <g id=\"ytick_1\">\n",
" <g id=\"line2d_7\">\n",
" <defs>\n",
" <path d=\"M 0 0 \n",
"L -3.5 0 \n",
"\" id=\"m7a20f2d7ac\" style=\"stroke:#000000;stroke-width:0.8;\"/>\n",
" </defs>\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m7a20f2d7ac\" y=\"223.594127\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_8\">\n",
" <!-- −1.2 -->\n",
" <g transform=\"translate(20.878125 227.393345)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 10.59375 35.5 \n",
"L 73.1875 35.5 \n",
"L 73.1875 27.203125 \n",
"L 10.59375 27.203125 \n",
"z\n",
"\" id=\"DejaVuSans-8722\"/>\n",
" <path d=\"M 10.6875 12.40625 \n",
"L 21 12.40625 \n",
"L 21 0 \n",
"L 10.6875 0 \n",
"z\n",
"\" id=\"DejaVuSans-46\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-50\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_2\">\n",
" <g id=\"line2d_8\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m7a20f2d7ac\" y=\"195.894119\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_9\">\n",
" <!-- −1.0 -->\n",
" <g transform=\"translate(20.878125 199.693338)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_3\">\n",
" <g id=\"line2d_9\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m7a20f2d7ac\" y=\"168.194112\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_10\">\n",
" <!-- −0.8 -->\n",
" <g transform=\"translate(20.878125 171.993331)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-56\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_4\">\n",
" <g id=\"line2d_10\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m7a20f2d7ac\" y=\"140.494104\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_11\">\n",
" <!-- −0.6 -->\n",
" <g transform=\"translate(20.878125 144.293323)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-54\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_5\">\n",
" <g id=\"line2d_11\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m7a20f2d7ac\" y=\"112.794097\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_12\">\n",
" <!-- −0.4 -->\n",
" <g transform=\"translate(20.878125 116.593316)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-52\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_6\">\n",
" <g id=\"line2d_12\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m7a20f2d7ac\" y=\"85.09409\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_13\">\n",
" <!-- −0.2 -->\n",
" <g transform=\"translate(20.878125 88.893308)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-50\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_7\">\n",
" <g id=\"line2d_13\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m7a20f2d7ac\" y=\"57.394082\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_14\">\n",
" <!-- 0.0 -->\n",
" <g transform=\"translate(29.257812 61.193301)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_8\">\n",
" <g id=\"line2d_14\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m7a20f2d7ac\" y=\"29.694075\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_15\">\n",
" <!-- 0.2 -->\n",
" <g transform=\"translate(29.257812 33.493294)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"95.410156\" xlink:href=\"#DejaVuSans-50\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_16\">\n",
" <!-- Energy (Ha) -->\n",
" <g transform=\"translate(14.798437 145.741094)rotate(-90)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 9.8125 72.90625 \n",
"L 55.90625 72.90625 \n",
"L 55.90625 64.59375 \n",
"L 19.671875 64.59375 \n",
"L 19.671875 43.015625 \n",
"L 54.390625 43.015625 \n",
"L 54.390625 34.71875 \n",
"L 19.671875 34.71875 \n",
"L 19.671875 8.296875 \n",
"L 56.78125 8.296875 \n",
"L 56.78125 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-69\"/>\n",
" <path d=\"M 45.40625 27.984375 \n",
"Q 45.40625 37.75 41.375 43.109375 \n",
"Q 37.359375 48.484375 30.078125 48.484375 \n",
"Q 22.859375 48.484375 18.828125 43.109375 \n",
"Q 14.796875 37.75 14.796875 27.984375 \n",
"Q 14.796875 18.265625 18.828125 12.890625 \n",
"Q 22.859375 7.515625 30.078125 7.515625 \n",
"Q 37.359375 7.515625 41.375 12.890625 \n",
"Q 45.40625 18.265625 45.40625 27.984375 \n",
"z\n",
"M 54.390625 6.78125 \n",
"Q 54.390625 -7.171875 48.1875 -13.984375 \n",
"Q 42 -20.796875 29.203125 -20.796875 \n",
"Q 24.46875 -20.796875 20.265625 -20.09375 \n",
"Q 16.0625 -19.390625 12.109375 -17.921875 \n",
"L 12.109375 -9.1875 \n",
"Q 16.0625 -11.328125 19.921875 -12.34375 \n",
"Q 23.78125 -13.375 27.78125 -13.375 \n",
"Q 36.625 -13.375 41.015625 -8.765625 \n",
"Q 45.40625 -4.15625 45.40625 5.171875 \n",
"L 45.40625 9.625 \n",
"Q 42.625 4.78125 38.28125 2.390625 \n",
"Q 33.9375 0 27.875 0 \n",
"Q 17.828125 0 11.671875 7.65625 \n",
"Q 5.515625 15.328125 5.515625 27.984375 \n",
"Q 5.515625 40.671875 11.671875 48.328125 \n",
"Q 17.828125 56 27.875 56 \n",
"Q 33.9375 56 38.28125 53.609375 \n",
"Q 42.625 51.21875 45.40625 46.390625 \n",
"L 45.40625 54.6875 \n",
"L 54.390625 54.6875 \n",
"z\n",
"\" id=\"DejaVuSans-103\"/>\n",
" <path d=\"M 32.171875 -5.078125 \n",
"Q 28.375 -14.84375 24.75 -17.8125 \n",
"Q 21.140625 -20.796875 15.09375 -20.796875 \n",
"L 7.90625 -20.796875 \n",
"L 7.90625 -13.28125 \n",
"L 13.1875 -13.28125 \n",
"Q 16.890625 -13.28125 18.9375 -11.515625 \n",
"Q 21 -9.765625 23.484375 -3.21875 \n",
"L 25.09375 0.875 \n",
"L 2.984375 54.6875 \n",
"L 12.5 54.6875 \n",
"L 29.59375 11.921875 \n",
"L 46.6875 54.6875 \n",
"L 56.203125 54.6875 \n",
"z\n",
"\" id=\"DejaVuSans-121\"/>\n",
" <path d=\"M 31 75.875 \n",
"Q 24.46875 64.65625 21.28125 53.65625 \n",
"Q 18.109375 42.671875 18.109375 31.390625 \n",
"Q 18.109375 20.125 21.3125 9.0625 \n",
"Q 24.515625 -2 31 -13.1875 \n",
"L 23.1875 -13.1875 \n",
"Q 15.875 -1.703125 12.234375 9.375 \n",
"Q 8.59375 20.453125 8.59375 31.390625 \n",
"Q 8.59375 42.28125 12.203125 53.3125 \n",
"Q 15.828125 64.359375 23.1875 75.875 \n",
"z\n",
"\" id=\"DejaVuSans-40\"/>\n",
" <path d=\"M 9.8125 72.90625 \n",
"L 19.671875 72.90625 \n",
"L 19.671875 43.015625 \n",
"L 55.515625 43.015625 \n",
"L 55.515625 72.90625 \n",
"L 65.375 72.90625 \n",
"L 65.375 0 \n",
"L 55.515625 0 \n",
"L 55.515625 34.71875 \n",
"L 19.671875 34.71875 \n",
"L 19.671875 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-72\"/>\n",
" <path d=\"M 8.015625 75.875 \n",
"L 15.828125 75.875 \n",
"Q 23.140625 64.359375 26.78125 53.3125 \n",
"Q 30.421875 42.28125 30.421875 31.390625 \n",
"Q 30.421875 20.453125 26.78125 9.375 \n",
"Q 23.140625 -1.703125 15.828125 -13.1875 \n",
"L 8.015625 -13.1875 \n",
"Q 14.5 -2 17.703125 9.0625 \n",
"Q 20.90625 20.125 20.90625 31.390625 \n",
"Q 20.90625 42.671875 17.703125 53.65625 \n",
"Q 14.5 64.65625 8.015625 75.875 \n",
"z\n",
"\" id=\"DejaVuSans-41\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-69\"/>\n",
" <use x=\"63.183594\" xlink:href=\"#DejaVuSans-110\"/>\n",
" <use x=\"126.5625\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"188.085938\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"227.449219\" xlink:href=\"#DejaVuSans-103\"/>\n",
" <use x=\"290.925781\" xlink:href=\"#DejaVuSans-121\"/>\n",
" <use x=\"350.105469\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"381.892578\" xlink:href=\"#DejaVuSans-40\"/>\n",
" <use x=\"420.90625\" xlink:href=\"#DejaVuSans-72\"/>\n",
" <use x=\"496.101562\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"557.380859\" xlink:href=\"#DejaVuSans-41\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"line2d_15\">\n",
" <path clip-path=\"url(#pbfd4c8560f)\" d=\"M 67.379119 17.083636 \n",
"L 70.453499 59.162431 \n",
"L 73.52788 79.407506 \n",
"L 76.60226 95.210999 \n",
"L 79.67664 115.446164 \n",
"L 82.75102 131.715299 \n",
"L 85.8254 141.174561 \n",
"L 88.89978 146.302209 \n",
"L 91.974161 149.293451 \n",
"L 95.048541 151.575729 \n",
"L 98.122921 154.266659 \n",
"L 101.197301 157.17722 \n",
"L 104.271681 159.795712 \n",
"L 107.346061 161.931274 \n",
"L 110.420442 163.915613 \n",
"L 113.494822 166.376486 \n",
"L 116.569202 169.759944 \n",
"L 119.643582 174.169725 \n",
"L 122.717962 179.458996 \n",
"L 125.792342 185.234189 \n",
"L 128.866723 190.851049 \n",
"L 131.941103 195.617314 \n",
"L 135.015483 199.160219 \n",
"L 138.089863 201.693139 \n",
"L 141.164243 203.707113 \n",
"L 144.238623 205.277677 \n",
"L 147.313004 206.065487 \n",
"L 150.387384 206.009472 \n",
"L 153.461764 205.744671 \n",
"L 156.536144 206.226523 \n",
"L 159.610524 207.918238 \n",
"L 162.684904 210.307467 \n",
"L 165.759285 212.223385 \n",
"L 168.833665 212.775448 \n",
"L 171.908045 212.084488 \n",
"L 174.982425 211.071191 \n",
"L 178.056805 210.636355 \n",
"L 181.131185 211.074441 \n",
"L 184.205566 212.070507 \n",
"L 187.279946 213.082506 \n",
"L 190.354326 213.691593 \n",
"L 193.428706 213.736827 \n",
"L 196.503086 213.341923 \n",
"L 199.577466 212.868223 \n",
"L 202.651847 212.715921 \n",
"L 205.726227 213.035753 \n",
"L 208.800607 213.603043 \n",
"L 211.874987 214.018049 \n",
"L 214.949367 214.061001 \n",
"L 218.023747 213.848249 \n",
"L 221.098128 213.659017 \n",
"L 224.172508 213.664885 \n",
"L 227.246888 213.835347 \n",
"L 230.321268 214.041707 \n",
"L 233.395648 214.193222 \n",
"L 236.470028 214.272251 \n",
"L 239.544409 214.293527 \n",
"L 242.618789 214.282296 \n",
"L 245.693169 214.282259 \n",
"L 248.767549 214.335711 \n",
"L 251.841929 214.437753 \n",
"L 254.916309 214.534153 \n",
"L 257.99069 214.579094 \n",
"L 261.06507 214.580142 \n",
"L 264.13945 214.576204 \n",
"L 267.21383 214.588764 \n",
"L 270.28821 214.612231 \n",
"L 273.36259 214.638786 \n",
"L 276.436971 214.668014 \n",
"L 279.511351 214.693322 \n",
"L 282.585731 214.701257 \n",
"L 285.660111 214.691601 \n",
"L 288.734491 214.683392 \n",
"L 291.808871 214.692365 \n",
"L 294.883252 214.712222 \n",
"L 297.957632 214.725843 \n",
"L 301.032012 214.726955 \n",
"L 304.106392 214.722567 \n",
"L 307.180772 214.720176 \n",
"L 310.255152 214.721699 \n",
"L 313.329533 214.72684 \n",
"L 316.403913 214.733977 \n",
"L 319.478293 214.738464 \n",
"L 322.552673 214.736764 \n",
"L 325.627053 214.732428 \n",
"L 328.701433 214.732605 \n",
"L 331.775814 214.73841 \n",
"L 334.850194 214.743692 \n",
"L 337.924574 214.743867 \n",
"L 340.998954 214.741263 \n",
"L 344.073334 214.740513 \n",
"L 347.147714 214.742716 \n",
"L 350.222095 214.745901 \n",
"L 353.296475 214.748198 \n",
"L 356.370855 214.74876 \n",
"L 359.445235 214.747765 \n",
"L 362.519615 214.746894 \n",
"L 365.593995 214.748086 \n",
"L 368.668376 214.750921 \n",
"L 371.742756 214.752832 \n",
"\" style=\"fill:none;stroke:#ff0000;stroke-linecap:square;stroke-opacity:0.7;stroke-width:1.5;\"/>\n",
" </g>\n",
" <g id=\"line2d_16\">\n",
" <path clip-path=\"url(#pbfd4c8560f)\" d=\"M 67.379119 214.756364 \n",
"L 70.453499 214.756364 \n",
"L 73.52788 214.756364 \n",
"L 76.60226 214.756364 \n",
"L 79.67664 214.756364 \n",
"L 82.75102 214.756364 \n",
"L 85.8254 214.756364 \n",
"L 88.89978 214.756364 \n",
"L 91.974161 214.756364 \n",
"L 95.048541 214.756364 \n",
"L 98.122921 214.756364 \n",
"L 101.197301 214.756364 \n",
"L 104.271681 214.756364 \n",
"L 107.346061 214.756364 \n",
"L 110.420442 214.756364 \n",
"L 113.494822 214.756364 \n",
"L 116.569202 214.756364 \n",
"L 119.643582 214.756364 \n",
"L 122.717962 214.756364 \n",
"L 125.792342 214.756364 \n",
"L 128.866723 214.756364 \n",
"L 131.941103 214.756364 \n",
"L 135.015483 214.756364 \n",
"L 138.089863 214.756364 \n",
"L 141.164243 214.756364 \n",
"L 144.238623 214.756364 \n",
"L 147.313004 214.756364 \n",
"L 150.387384 214.756364 \n",
"L 153.461764 214.756364 \n",
"L 156.536144 214.756364 \n",
"L 159.610524 214.756364 \n",
"L 162.684904 214.756364 \n",
"L 165.759285 214.756364 \n",
"L 168.833665 214.756364 \n",
"L 171.908045 214.756364 \n",
"L 174.982425 214.756364 \n",
"L 178.056805 214.756364 \n",
"L 181.131185 214.756364 \n",
"L 184.205566 214.756364 \n",
"L 187.279946 214.756364 \n",
"L 190.354326 214.756364 \n",
"L 193.428706 214.756364 \n",
"L 196.503086 214.756364 \n",
"L 199.577466 214.756364 \n",
"L 202.651847 214.756364 \n",
"L 205.726227 214.756364 \n",
"L 208.800607 214.756364 \n",
"L 211.874987 214.756364 \n",
"L 214.949367 214.756364 \n",
"L 218.023747 214.756364 \n",
"L 221.098128 214.756364 \n",
"L 224.172508 214.756364 \n",
"L 227.246888 214.756364 \n",
"L 230.321268 214.756364 \n",
"L 233.395648 214.756364 \n",
"L 236.470028 214.756364 \n",
"L 239.544409 214.756364 \n",
"L 242.618789 214.756364 \n",
"L 245.693169 214.756364 \n",
"L 248.767549 214.756364 \n",
"L 251.841929 214.756364 \n",
"L 254.916309 214.756364 \n",
"L 257.99069 214.756364 \n",
"L 261.06507 214.756364 \n",
"L 264.13945 214.756364 \n",
"L 267.21383 214.756364 \n",
"L 270.28821 214.756364 \n",
"L 273.36259 214.756364 \n",
"L 276.436971 214.756364 \n",
"L 279.511351 214.756364 \n",
"L 282.585731 214.756364 \n",
"L 285.660111 214.756364 \n",
"L 288.734491 214.756364 \n",
"L 291.808871 214.756364 \n",
"L 294.883252 214.756364 \n",
"L 297.957632 214.756364 \n",
"L 301.032012 214.756364 \n",
"L 304.106392 214.756364 \n",
"L 307.180772 214.756364 \n",
"L 310.255152 214.756364 \n",
"L 313.329533 214.756364 \n",
"L 316.403913 214.756364 \n",
"L 319.478293 214.756364 \n",
"L 322.552673 214.756364 \n",
"L 325.627053 214.756364 \n",
"L 328.701433 214.756364 \n",
"L 331.775814 214.756364 \n",
"L 334.850194 214.756364 \n",
"L 337.924574 214.756364 \n",
"L 340.998954 214.756364 \n",
"L 344.073334 214.756364 \n",
"L 347.147714 214.756364 \n",
"L 350.222095 214.756364 \n",
"L 353.296475 214.756364 \n",
"L 356.370855 214.756364 \n",
"L 359.445235 214.756364 \n",
"L 362.519615 214.756364 \n",
"L 365.593995 214.756364 \n",
"L 368.668376 214.756364 \n",
"L 371.742756 214.756364 \n",
"\" style=\"fill:none;stroke:#0000ff;stroke-dasharray:1.5,2.475;stroke-dashoffset:0;stroke-opacity:0.7;stroke-width:1.5;\"/>\n",
" </g>\n",
" <g id=\"patch_3\">\n",
" <path d=\"M 52.160938 224.64 \n",
"L 52.160938 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_4\">\n",
" <path d=\"M 386.960938 224.64 \n",
"L 386.960938 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_5\">\n",
" <path d=\"M 52.160938 224.64 \n",
"L 386.960938 224.64 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_6\">\n",
" <path d=\"M 52.160938 7.2 \n",
"L 386.960938 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"legend_1\">\n",
" <g id=\"patch_7\">\n",
" <path d=\"M 244.220312 44.978125 \n",
"L 379.960938 44.978125 \n",
"Q 381.960938 44.978125 381.960938 42.978125 \n",
"L 381.960938 14.2 \n",
"Q 381.960938 12.2 379.960938 12.2 \n",
"L 244.220312 12.2 \n",
"Q 242.220312 12.2 242.220312 14.2 \n",
"L 242.220312 42.978125 \n",
"Q 242.220312 44.978125 244.220312 44.978125 \n",
"z\n",
"\" style=\"fill:#ffffff;opacity:0.8;stroke:#cccccc;stroke-linejoin:miter;\"/>\n",
" </g>\n",
" <g id=\"line2d_17\">\n",
" <path d=\"M 246.220312 20.4 \n",
"L 266.220312 20.4 \n",
"\" style=\"fill:none;stroke:#ff0000;stroke-linecap:square;stroke-opacity:0.7;stroke-width:1.5;\"/>\n",
" </g>\n",
" <g id=\"line2d_18\"/>\n",
" <g id=\"text_17\">\n",
" <!-- $\\left\\langle {\\psi \\left( {\\theta } \\right)} \\right|H\\left| {\\psi \\left( {\\theta } \\right)} \\right\\rangle $ -->\n",
" <g transform=\"translate(274.220312 23.9)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 8.9375 31.34375 \n",
"L 22.703125 75.875 \n",
"L 31 75.875 \n",
"L 17.234375 31.34375 \n",
"L 31 -13.1875 \n",
"L 22.703125 -13.1875 \n",
"z\n",
"\" id=\"DejaVuSans-10216\"/>\n",
" <path d=\"M 24.859375 -1.21875 \n",
"Q 13.921875 0.59375 9.625 5.328125 \n",
"Q 4.34375 11.140625 6.640625 23 \n",
"L 12.796875 54.6875 \n",
"L 21.875 54.6875 \n",
"L 15.765625 23.34375 \n",
"Q 14.0625 14.40625 17.484375 10.6875 \n",
"Q 20.515625 7.46875 26.421875 6.78125 \n",
"L 35.6875 54.6875 \n",
"L 44.625 54.6875 \n",
"L 35.359375 6.84375 \n",
"Q 41.890625 7.515625 45.75 10.75 \n",
"Q 50.734375 14.84375 52.390625 23.390625 \n",
"L 58.453125 54.6875 \n",
"L 67.53125 54.6875 \n",
"L 61.375 23.046875 \n",
"Q 58.984375 10.75 51.5625 5.375 \n",
"Q 44.875 0.53125 33.796875 -1.171875 \n",
"L 29.984375 -20.796875 \n",
"L 21.046875 -20.796875 \n",
"z\n",
"\" id=\"DejaVuSans-Oblique-968\"/>\n",
" <path d=\"M 45.515625 34.671875 \n",
"L 14.453125 34.671875 \n",
"Q 12.359375 20.0625 14.5 13.875 \n",
"Q 17.1875 6.25 24.46875 6.25 \n",
"Q 31.78125 6.25 37.359375 13.921875 \n",
"Q 42.234375 20.65625 45.515625 34.671875 \n",
"z\n",
"M 47.015625 42.96875 \n",
"Q 48.34375 56.84375 46.625 61.71875 \n",
"Q 43.953125 69.4375 36.765625 69.4375 \n",
"Q 29.296875 69.4375 23.828125 61.8125 \n",
"Q 19.53125 55.671875 16.15625 42.96875 \n",
"z\n",
"M 38.1875 76.765625 \n",
"Q 49.90625 76.765625 54.59375 66.40625 \n",
"Q 59.28125 56.109375 55.71875 37.84375 \n",
"Q 52.203125 19.625 43.453125 9.28125 \n",
"Q 34.765625 -1.125 23.046875 -1.125 \n",
"Q 11.28125 -1.125 6.640625 9.28125 \n",
"Q 2 19.625 5.515625 37.84375 \n",
"Q 9.078125 56.109375 17.71875 66.40625 \n",
"Q 26.421875 76.765625 38.1875 76.765625 \n",
"z\n",
"\" id=\"DejaVuSans-Oblique-952\"/>\n",
" <path d=\"M 21 76.421875 \n",
"L 21 -23.578125 \n",
"L 12.703125 -23.578125 \n",
"L 12.703125 76.421875 \n",
"z\n",
"\" id=\"DejaVuSans-124\"/>\n",
" <path d=\"M 16.890625 72.90625 \n",
"L 26.8125 72.90625 \n",
"L 21 43.015625 \n",
"L 56.78125 43.015625 \n",
"L 62.59375 72.90625 \n",
"L 72.515625 72.90625 \n",
"L 58.296875 0 \n",
"L 48.390625 0 \n",
"L 55.171875 34.71875 \n",
"L 19.390625 34.71875 \n",
"L 12.59375 0 \n",
"L 2.6875 0 \n",
"z\n",
"\" id=\"DejaVuSans-Oblique-72\"/>\n",
" <path d=\"M 30.078125 31.34375 \n",
"L 16.3125 -13.1875 \n",
"L 8.015625 -13.1875 \n",
"L 21.78125 31.34375 \n",
"L 8.015625 75.875 \n",
"L 16.3125 75.875 \n",
"z\n",
"\" id=\"DejaVuSans-10217\"/>\n",
" </defs>\n",
" <use transform=\"translate(0 0.234375)\" xlink:href=\"#DejaVuSans-10216\"/>\n",
" <use transform=\"translate(39.013672 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-968\"/>\n",
" <use transform=\"translate(104.980469 0.234375)\" xlink:href=\"#DejaVuSans-40\"/>\n",
" <use transform=\"translate(143.994141 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-952\"/>\n",
" <use transform=\"translate(205.175781 0.234375)\" xlink:href=\"#DejaVuSans-41\"/>\n",
" <use transform=\"translate(244.189453 0.234375)\" xlink:href=\"#DejaVuSans-124\"/>\n",
" <use transform=\"translate(277.880859 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-72\"/>\n",
" <use transform=\"translate(353.076172 0.234375)\" xlink:href=\"#DejaVuSans-124\"/>\n",
" <use transform=\"translate(386.767578 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-968\"/>\n",
" <use transform=\"translate(452.734375 0.234375)\" xlink:href=\"#DejaVuSans-40\"/>\n",
" <use transform=\"translate(491.748047 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-952\"/>\n",
" <use transform=\"translate(552.929688 0.234375)\" xlink:href=\"#DejaVuSans-41\"/>\n",
" <use transform=\"translate(591.943359 0.234375)\" xlink:href=\"#DejaVuSans-10217\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"line2d_19\">\n",
" <path d=\"M 246.220312 35.398437 \n",
"L 266.220312 35.398437 \n",
"\" style=\"fill:none;stroke:#0000ff;stroke-dasharray:1.5,2.475;stroke-dashoffset:0;stroke-opacity:0.7;stroke-width:1.5;\"/>\n",
" </g>\n",
" <g id=\"line2d_20\"/>\n",
" <g id=\"text_18\">\n",
" <!-- Ground-state energy -->\n",
" <g transform=\"translate(274.220312 38.898437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 59.515625 10.40625 \n",
"L 59.515625 29.984375 \n",
"L 43.40625 29.984375 \n",
"L 43.40625 38.09375 \n",
"L 69.28125 38.09375 \n",
"L 69.28125 6.78125 \n",
"Q 63.578125 2.734375 56.6875 0.65625 \n",
"Q 49.8125 -1.421875 42 -1.421875 \n",
"Q 24.90625 -1.421875 15.25 8.5625 \n",
"Q 5.609375 18.5625 5.609375 36.375 \n",
"Q 5.609375 54.25 15.25 64.234375 \n",
"Q 24.90625 74.21875 42 74.21875 \n",
"Q 49.125 74.21875 55.546875 72.453125 \n",
"Q 61.96875 70.703125 67.390625 67.28125 \n",
"L 67.390625 56.78125 \n",
"Q 61.921875 61.421875 55.765625 63.765625 \n",
"Q 49.609375 66.109375 42.828125 66.109375 \n",
"Q 29.4375 66.109375 22.71875 58.640625 \n",
"Q 16.015625 51.171875 16.015625 36.375 \n",
"Q 16.015625 21.625 22.71875 14.15625 \n",
"Q 29.4375 6.6875 42.828125 6.6875 \n",
"Q 48.046875 6.6875 52.140625 7.59375 \n",
"Q 56.25 8.5 59.515625 10.40625 \n",
"z\n",
"\" id=\"DejaVuSans-71\"/>\n",
" <path d=\"M 45.40625 46.390625 \n",
"L 45.40625 75.984375 \n",
"L 54.390625 75.984375 \n",
"L 54.390625 0 \n",
"L 45.40625 0 \n",
"L 45.40625 8.203125 \n",
"Q 42.578125 3.328125 38.25 0.953125 \n",
"Q 33.9375 -1.421875 27.875 -1.421875 \n",
"Q 17.96875 -1.421875 11.734375 6.484375 \n",
"Q 5.515625 14.40625 5.515625 27.296875 \n",
"Q 5.515625 40.1875 11.734375 48.09375 \n",
"Q 17.96875 56 27.875 56 \n",
"Q 33.9375 56 38.25 53.625 \n",
"Q 42.578125 51.265625 45.40625 46.390625 \n",
"z\n",
"M 14.796875 27.296875 \n",
"Q 14.796875 17.390625 18.875 11.75 \n",
"Q 22.953125 6.109375 30.078125 6.109375 \n",
"Q 37.203125 6.109375 41.296875 11.75 \n",
"Q 45.40625 17.390625 45.40625 27.296875 \n",
"Q 45.40625 37.203125 41.296875 42.84375 \n",
"Q 37.203125 48.484375 30.078125 48.484375 \n",
"Q 22.953125 48.484375 18.875 42.84375 \n",
"Q 14.796875 37.203125 14.796875 27.296875 \n",
"z\n",
"\" id=\"DejaVuSans-100\"/>\n",
" <path d=\"M 4.890625 31.390625 \n",
"L 31.203125 31.390625 \n",
"L 31.203125 23.390625 \n",
"L 4.890625 23.390625 \n",
"z\n",
"\" id=\"DejaVuSans-45\"/>\n",
" <path d=\"M 44.28125 53.078125 \n",
"L 44.28125 44.578125 \n",
"Q 40.484375 46.53125 36.375 47.5 \n",
"Q 32.28125 48.484375 27.875 48.484375 \n",
"Q 21.1875 48.484375 17.84375 46.4375 \n",
"Q 14.5 44.390625 14.5 40.28125 \n",
"Q 14.5 37.15625 16.890625 35.375 \n",
"Q 19.28125 33.59375 26.515625 31.984375 \n",
"L 29.59375 31.296875 \n",
"Q 39.15625 29.25 43.1875 25.515625 \n",
"Q 47.21875 21.78125 47.21875 15.09375 \n",
"Q 47.21875 7.46875 41.1875 3.015625 \n",
"Q 35.15625 -1.421875 24.609375 -1.421875 \n",
"Q 20.21875 -1.421875 15.453125 -0.5625 \n",
"Q 10.6875 0.296875 5.421875 2 \n",
"L 5.421875 11.28125 \n",
"Q 10.40625 8.6875 15.234375 7.390625 \n",
"Q 20.0625 6.109375 24.8125 6.109375 \n",
"Q 31.15625 6.109375 34.5625 8.28125 \n",
"Q 37.984375 10.453125 37.984375 14.40625 \n",
"Q 37.984375 18.0625 35.515625 20.015625 \n",
"Q 33.0625 21.96875 24.703125 23.78125 \n",
"L 21.578125 24.515625 \n",
"Q 13.234375 26.265625 9.515625 29.90625 \n",
"Q 5.8125 33.546875 5.8125 39.890625 \n",
"Q 5.8125 47.609375 11.28125 51.796875 \n",
"Q 16.75 56 26.8125 56 \n",
"Q 31.78125 56 36.171875 55.265625 \n",
"Q 40.578125 54.546875 44.28125 53.078125 \n",
"z\n",
"\" id=\"DejaVuSans-115\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-71\"/>\n",
" <use x=\"77.490234\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"116.353516\" xlink:href=\"#DejaVuSans-111\"/>\n",
" <use x=\"177.535156\" xlink:href=\"#DejaVuSans-117\"/>\n",
" <use x=\"240.914062\" xlink:href=\"#DejaVuSans-110\"/>\n",
" <use x=\"304.292969\" xlink:href=\"#DejaVuSans-100\"/>\n",
" <use x=\"367.769531\" xlink:href=\"#DejaVuSans-45\"/>\n",
" <use x=\"403.853516\" xlink:href=\"#DejaVuSans-115\"/>\n",
" <use x=\"455.953125\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"495.162109\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"556.441406\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"595.650391\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"657.173828\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"688.960938\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"750.484375\" xlink:href=\"#DejaVuSans-110\"/>\n",
" <use x=\"813.863281\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"875.386719\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"914.75\" xlink:href=\"#DejaVuSans-103\"/>\n",
" <use x=\"978.226562\" xlink:href=\"#DejaVuSans-121\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <defs>\n",
" <clipPath id=\"pbfd4c8560f\">\n",
" <rect height=\"217.44\" width=\"334.8\" x=\"52.160938\" y=\"7.2\"/>\n",
" </clipPath>\n",
" </defs>\n",
"</svg>\n"
],
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -1938,7 +618,7 @@ ...@@ -1938,7 +618,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.8" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -110,8 +110,8 @@ ...@@ -110,8 +110,8 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:04.537224Z", "end_time": "2021-03-09T03:39:38.503998Z",
"start_time": "2021-01-09T07:26:00.836470Z" "start_time": "2021-03-09T03:39:35.006563Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -119,7 +119,6 @@ ...@@ -119,7 +119,6 @@
"import os\n", "import os\n",
"import platform\n", "import platform\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"%config InlineBackend.figure_format = 'svg'\n",
"from IPython.display import clear_output\n", "from IPython.display import clear_output\n",
"\n", "\n",
"import numpy\n", "import numpy\n",
...@@ -127,8 +126,7 @@ ...@@ -127,8 +126,7 @@
"from numpy import pi as PI\n", "from numpy import pi as PI\n",
"from numpy import savez, zeros\n", "from numpy import savez, zeros\n",
"\n", "\n",
"from paddle import fluid\n", "import paddle\n",
"from paddle.complex import matmul, transpose\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import pauli_str_to_matrix\n", "from paddle_quantum.utils import pauli_str_to_matrix\n",
"from paddle_quantum.VQE.chemistrysub import H2_generator" "from paddle_quantum.VQE.chemistrysub import H2_generator"
...@@ -146,8 +144,8 @@ ...@@ -146,8 +144,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:04.570840Z", "end_time": "2021-03-09T03:39:38.515263Z",
"start_time": "2021-01-09T07:26:04.544640Z" "start_time": "2021-03-09T03:39:38.507179Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -167,13 +165,13 @@ ...@@ -167,13 +165,13 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:07.190974Z", "end_time": "2021-02-27T13:57:33.364017Z",
"start_time": "2021-01-09T07:26:05.431945Z" "start_time": "2021-02-27T13:57:30.969092Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"!pip install openfermion==0.11.0\n", "!pip install openfermion\n",
"clear_output()" "clear_output()"
] ]
}, },
...@@ -182,23 +180,23 @@ ...@@ -182,23 +180,23 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:09.219268Z", "end_time": "2021-02-27T13:57:35.854193Z",
"start_time": "2021-01-09T07:26:07.195371Z" "start_time": "2021-02-27T13:57:33.368266Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"!pip install openfermionpyscf==0.4\n", "!pip install openfermionpyscf\n",
"clear_output()" "clear_output()"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:10.031901Z", "end_time": "2021-03-09T03:39:44.013859Z",
"start_time": "2021-01-09T07:26:09.224389Z" "start_time": "2021-03-09T03:39:40.605688Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -207,21 +205,21 @@ ...@@ -207,21 +205,21 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"The generated h2 Hamiltonian is \n", "The generated h2 Hamiltonian is \n",
" (-0.04207897647782281+0j) [] +\n", " -0.042078976477822494 [] +\n",
"(-0.04475014401535161+0j) [X0 X1 Y2 Y3] +\n", "-0.04475014401535163 [X0 X1 Y2 Y3] +\n",
"(0.04475014401535161+0j) [X0 Y1 Y2 X3] +\n", "0.04475014401535163 [X0 Y1 Y2 X3] +\n",
"(0.04475014401535161+0j) [Y0 X1 X2 Y3] +\n", "0.04475014401535163 [Y0 X1 X2 Y3] +\n",
"(-0.04475014401535161+0j) [Y0 Y1 X2 X3] +\n", "-0.04475014401535163 [Y0 Y1 X2 X3] +\n",
"(0.17771287465139946+0j) [Z0] +\n", "0.17771287465139946 [Z0] +\n",
"(0.17059738328801055+0j) [Z0 Z1] +\n", "0.17059738328801055 [Z0 Z1] +\n",
"(0.12293305056183798+0j) [Z0 Z2] +\n", "0.12293305056183797 [Z0 Z2] +\n",
"(0.16768319457718958+0j) [Z0 Z3] +\n", "0.1676831945771896 [Z0 Z3] +\n",
"(0.1777128746513994+0j) [Z1] +\n", "0.17771287465139946 [Z1] +\n",
"(0.16768319457718958+0j) [Z1 Z2] +\n", "0.1676831945771896 [Z1 Z2] +\n",
"(0.12293305056183798+0j) [Z1 Z3] +\n", "0.12293305056183797 [Z1 Z3] +\n",
"(-0.24274280513140456+0j) [Z2] +\n", "-0.24274280513140462 [Z2] +\n",
"(0.17627640804319586+0j) [Z2 Z3] +\n", "0.1762764080431959 [Z2 Z3] +\n",
"(-0.24274280513140456+0j) [Z3]\n" "-0.24274280513140462 [Z3]\n"
] ]
} }
], ],
...@@ -232,21 +230,20 @@ ...@@ -232,21 +230,20 @@
"# Decide which operating system the user is using\n", "# Decide which operating system the user is using\n",
"if sysStr in ('Linux', 'Darwin'):\n", "if sysStr in ('Linux', 'Darwin'):\n",
"\n", "\n",
" import openfermion\n", " import openfermion \n",
" import openfermionpyscf\n", " import openfermionpyscf \n",
"\n", "\n",
" # Please check whether the geometric configuration file of h2 is downloaded correctly\n", " # Please check whether the geometric configuration file of h2 is downloaded correctly\n",
" geo = 'h2.xyz'\n", " geometry = 'h2.xyz'\n",
" # geometry = [('H', (0.0, 0.0, 0.0)), ('H', (0.0, 0.0, 0.74))]\n",
" basis = 'sto-3g'\n",
" charge = 0\n", " charge = 0\n",
" multiplicity = 1\n", " multiplicity = 1\n",
"\n", "\n",
" # Generate Hamiltonian\n", " # Generate Hamiltonian\n",
" mol = openfermion.hamiltonians.MolecularData(geo, 'sto-3g', multiplicity, charge)\n", " molecular_hamiltonian = openfermionpyscf.generate_molecular_hamiltonian(geometry, basis, multiplicity, charge)\n",
" openfermionpyscf.run_pyscf(mol)\n", " qubit_op = openfermion.transforms.jordan_wigner(molecular_hamiltonian)\n",
" terms_molecular_hamiltonian = mol.get_molecular_hamiltonian()\n", " \n",
" fermionic_hamiltonian = openfermion.transforms.get_fermion_operator(terms_molecular_hamiltonian)\n",
" qubit_op = openfermion.transforms.jordan_wigner(fermionic_hamiltonian)\n",
"\n",
" # Print result\n", " # Print result\n",
" print(\"The generated h2 Hamiltonian is \\n\", qubit_op)" " print(\"The generated h2 Hamiltonian is \\n\", qubit_op)"
] ]
...@@ -263,11 +260,11 @@ ...@@ -263,11 +260,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:11.884870Z", "end_time": "2021-03-09T03:39:44.035716Z",
"start_time": "2021-01-09T07:26:11.875694Z" "start_time": "2021-03-09T03:39:44.017820Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -318,11 +315,11 @@ ...@@ -318,11 +315,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:13.717206Z", "end_time": "2021-03-09T03:39:44.048908Z",
"start_time": "2021-01-09T07:26:13.709627Z" "start_time": "2021-03-09T03:39:44.040479Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -369,23 +366,24 @@ ...@@ -369,23 +366,24 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:15.661433Z", "end_time": "2021-03-09T03:39:44.060734Z",
"start_time": "2021-01-09T07:26:15.654903Z" "start_time": "2021-03-09T03:39:44.052212Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"class StateNet(fluid.dygraph.Layer):\n", "class StateNet(paddle.nn.Layer):\n",
"\n", "\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " def __init__(self, shape, dtype=\"float64\"):\n",
" low=0.0, high=2 * PI), dtype=\"float64\"):\n",
" super(StateNet, self).__init__()\n", " super(StateNet, self).__init__()\n",
" \n", " \n",
" # Initialize the theta parameter list and fill the initial value with a uniform distribution of [0, 2*pi]\n", " # Initialize the theta parameter list and fill the initial value with a uniform distribution of [0, 2*pi]\n",
" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.theta = self.create_parameter(shape=shape, \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self, N, D):\n", " def forward(self, N, D):\n",
...@@ -407,17 +405,17 @@ ...@@ -407,17 +405,17 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:17.770511Z", "end_time": "2021-03-09T03:39:44.579037Z",
"start_time": "2021-01-09T07:26:17.767150Z" "start_time": "2021-03-09T03:39:44.575023Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"ITR = 100 # Set the number of optimization iterations\n", "ITR = 80 # Set the number of optimization iterations\n",
"LR = 0.2 # Set the learning rate\n", "LR = 0.4 # Set the learning rate\n",
"D = 2 # Set the depth of the repetitive calculation module in QNN" "D = 2 # Set the depth of the repetitive calculation module in QNN"
] ]
}, },
...@@ -427,17 +425,16 @@ ...@@ -427,17 +425,16 @@
"source": [ "source": [
"### Training\n", "### Training\n",
"\n", "\n",
"After all the training model parameters are set, we convert the data into variables in the Paddle dynamic computational graph, and then train the quantum neural network. The results of the training process is stored in the summary_data file.\n", "After all the training model parameters are set, we convert the data into Tensor in the Paddle, and then train the quantum neural network. The results of the training process is stored in the summary_data file.\n"
"\n"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": 8,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:33.571665Z", "end_time": "2021-03-09T03:40:22.805429Z",
"start_time": "2021-01-09T07:26:19.157308Z" "start_time": "2021-03-09T03:39:57.972353Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -445,61 +442,54 @@ ...@@ -445,61 +442,54 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 20 loss: -0.8523\n", "iter: 20 loss: -1.0915\n",
"iter: 20 Ground state energy: -0.8523 Ha\n", "iter: 20 Ground state energy: -1.0915 Ha\n",
"iter: 40 loss: -1.1264\n", "iter: 40 loss: -1.1281\n",
"iter: 40 Ground state energy: -1.1264 Ha\n", "iter: 40 Ground state energy: -1.1281 Ha\n",
"iter: 60 loss: -1.1323\n", "iter: 60 loss: -1.1341\n",
"iter: 60 Ground state energy: -1.1323 Ha\n", "iter: 60 Ground state energy: -1.1341 Ha\n",
"iter: 80 loss: -1.1360\n", "iter: 80 loss: -1.1360\n",
"iter: 80 Ground state energy: -1.1360 Ha\n", "iter: 80 Ground state energy: -1.1360 Ha\n"
"iter: 100 loss: -1.1361\n",
"iter: 100 Ground state energy: -1.1361 Ha\n"
] ]
} }
], ],
"source": [ "source": [
"# Initialize Paddle dynamic computational graph\n", "# Determine the parameter dimension of the network\n",
"with fluid.dygraph.guard():\n", "net = StateNet(shape=[D + 1, N, 1])\n",
"\n", "\n",
"\n", "\n",
" # Determine the parameter dimension of the network\n", "# Generally speaking, we use Adam optimizer to obtain relatively good convergence,\n",
" net = StateNet(shape=[D + 1, N, 1])\n", "# You can change it to SGD or RMS prop.\n",
"opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"\n", "\n",
" \n", "# Record optimization results\n",
" # Generally speaking, we use Adam optimizer to obtain relatively good convergence,\n", "summary_iter, summary_loss = [], []\n",
" # You can change it to SGD or RMS prop.\n", "\n",
" opt = fluid.optimizer.AdamOptimizer(\n", "# Optimization loop\n",
" learning_rate=LR, parameter_list=net.parameters())\n", "for itr in range(1, ITR + 1):\n",
"\n",
" # Forward propagation to calculate loss function\n",
" loss = net(N, D)\n",
"\n",
" # Use back propagation to minimize the loss function\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" opt.clear_grad()\n",
"\n", "\n",
" # Record optimization results\n", " # Record optimization results\n",
" summary_iter, summary_loss = [], []\n", " summary_loss.append(loss.numpy())\n",
" \n", " summary_iter.append(itr)\n",
" # Optimization loop\n",
" for itr in range(1, ITR + 1):\n",
" \n",
" # Forward propagation to calculate loss function\n",
" loss = net(N, D)\n",
"\n", "\n",
" # Use back propagation to minimize the loss function\n", " # Print result\n",
" loss.backward()\n", " if itr % 20 == 0:\n",
" opt.minimize(loss)\n", " print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n",
" net.clear_gradients()\n", " print(\"iter:\", itr, \"Ground state energy:\", \"%.4f Ha\" \n",
" \n", " % loss.numpy())\n",
" # Record optimization results\n", "\n",
" summary_loss.append(loss.numpy())\n", "# Save the training results to the output folder\n",
" summary_iter.append(itr)\n", "os.makedirs(\"output\", exist_ok=True)\n",
" \n", "savez(\"./output/summary_data\", iter = summary_iter, \n",
" # Print result\n", " energy=summary_loss)"
" if itr % 20 == 0:\n",
" print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n",
" print(\"iter:\", itr, \"Ground state energy:\", \"%.4f Ha\" \n",
" % loss.numpy())\n",
"\n",
" # Save the training results to the output folder\n",
" os.makedirs(\"output\", exist_ok=True)\n",
" savez(\"./output/summary_data\", iter = summary_iter, \n",
" energy=summary_loss)"
] ]
}, },
{ {
...@@ -513,1265 +503,17 @@ ...@@ -513,1265 +503,17 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": 9,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T07:26:42.456121Z", "end_time": "2021-03-09T03:40:23.538082Z",
"start_time": "2021-01-09T07:26:41.495984Z" "start_time": "2021-03-09T03:40:22.810747Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/svg+xml": [ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAEGCAYAAAB7DNKzAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAyDklEQVR4nO3deXxU1fn48c9DQhKWhDUgghiQNSAEEhCrLLJaN3ArKv2KWrX6dW3d8FfbUm2L1lrrVveNVot+sSgqKoKgKBVJANkRhShRZEnYERKS5/fHuYlDmExCksmdmTzv12tec++dM/c+mZnMM+eee84RVcUYY4ypSAO/AzDGGBPZLFEYY4wJyRKFMcaYkCxRGGOMCckShTHGmJDi/Q6gtrVu3VrT0tL8DsMYY6JKTk7OdlVNDfZYzCWKtLQ0srOz/Q7DGGOiioh8XdFjdurJGGNMSJYojDHGhGSJwhhjTEgx10ZhTH1VVFREXl4eBw4c8DsUE8GSkpLo0KEDDRs2rPJzLFEYEyPy8vJITk4mLS0NEfE7HBOBVJX8/Hzy8vLo1KlTlZ9np56MiREHDhygVatWliRMhUSEVq1aHXWt0xKFMTHEkoSpTHU+I5YoSu3fDy+/DF984XckxhgTUSxRlCopgX//G9as8TsSY4yJKJYoSjVpAiKwZ4/fkRhjTESxRFFKBJo2tURhTC0YPnw4hw4dClnmhx9+YOjQoRQXFwNQXFzMTTfdRK9evTjxxBPZsGEDhYWFDBky5LB9DRs2jNzcXACefPJJrr322sP227t3b9Z4ZwYCy9Z2LDt27ODcc8+t0usR7SxRBEpOhr17/Y7CmKi2atUqWrVqRXx86Kvvn3vuOc477zzi4uIAmDJlCp07d2bVqlXceOON/OMf/yAhIYERI0bwyiuvBN3HihUr6N+/f9n6gQMHyM3NpVu3bkcVc3ViadGiBQUFBeTn5x/VsaKR9aMIlJwMu3f7HYUxNff007BhQ+3us3NnuOqqSou98cYbjBs3DoB+/frxzjvv8Oijj9KlSxc6derE448/zrRp03jppZd4+eWXAdi3bx8zZswgJycHgE6dOvH2228DMG7cOO68804mTJhwxLGWL1/O5ZdfXra+YsUKunXrVvaFHygcsZx55pm8+eabXHbZZVV5BaOWJYpAycmwc6ffURgT1WbNmsVbb73FoUOHKCgo4JhjjuHzzz/nggsu4KOPPqJv374UFhayYcMGSqcEmDNnDps2bSIjIwOAgoICRo4cCbhTSYsXLw56rFWrVnHeeeeVXfK5d+9ezjrrrCPKhSuWsWPHcscdd1iiqFeSk+Gbb/yOwpiaq8Iv/3DYv38/hYWFNG/enJUrV9KjRw8AVq9eTXp6Oo888gjnnXce27dvp3nz5mXPW7ZsGXfffTfXXHMNAFdeeSV9+vQBIC4ujoSEBPbs2UNycnLZczZt2kRqaipr164t23b99dcH7XG8du3asMTSvXt31q1bVwuvXGSzNopA1kZhTI00btwYEWHv3r2sW7eO7t27U1BQQNOmTUlISCA7O5sBAwbQqFGjw3oH79ixg8aNGwPu1//s2bM5++yzyx4/ePAgSUlJhx1rxYoV9OrV67Btq1evLvtSDxSuWL7++uujGgojWlmiCJSc7DreVXK1hjGmYmPGjOHdd98lISGBtWvXkp2dTd++ffnXv/5FWloabdq0oUWLFhQXF5d9QXfr1o1PP/0UgAcffJAzzzyz7As4Pz+f1q1bHzGI3fLly0lPTz9s26pVqzjxxBOPiClcsbzxxhuMHTu2tl66iGWJIlDTpu5+3z5/4zAmio0dO5bXX3+d008/nR49ejBhwgTmz59PdnY2U6dOLSs3evRoPv74YwAuvvhilixZQpcuXVi+fDl/+9vfysrNmzePM88884jjrFix4rBEUVBQgKpyzDHHHFE2XLG8+eab9SJRoKq+3YDTgXXAl8CkII8nAq94jy8C0irbZ2Zmplbbhx+qnnWW6qZN1d+HMT5ZvXq13yGUOfHEE7WoqEhVVS+77DKdPXv2EWVycnL05z//eaX7Ovfcc3XdunVl60OHDtWNGzdWKY7yZWszloKCAh08eHCV4og0wT4rQLZW8L3qW41CROKAx4CfAunAxSKSXq7YL4AdqtoFeBC4L6xBldYorNOdMTWyfPnysn4Uy5cvD9pu0L9/f0477bSyTm7BFBYWMm7cuKPuFxEqrtqKpUWLFnz00Ue1Elek8/Oqp4HAl6q6AUBEpgFjgdUBZcYCk73l6cCjIiJe9qt9pVdUWKIwptaU9kcI5oorrgj53ISEBC699NLDtl122WWHXaUUSvmytR1LfeFnomgPbApYzwNOqqiMqh4SkV1AK2B7YCERuRq4GqBjx47Vj8gShTER72j6LMR6/4a6EhON2ar6lKpmqWpWampq9XdkicIYY47gZ6L4FjguYL2Dty1oGRGJB5oB4RtYpXFjaNDAEoUxxgTwM1EsBrqKSCcRSQAuAmaWKzMTmOgtXwB8ELb2CfhxBFnrdGeMMWV8a6Pw2hyuB94D4oDnVHWViNyNu0xrJvAs8E8R+RIowCWT8LKBAY0x5jC+jvWkqrOAWeW2/S5g+QBwYZ0GZcN4GGPMYWKiMbtWWY3CmGrbsmULl1xyCZ07dyYzM5OTTz6ZGTNm1GkMubm59O7du8rl58+fz8KFC2utXCyyRFGe1SiMqRZVZdy4cQwZMoQNGzaQk5PDtGnTyMvLO6JsZbPf1aVoTBR1/fpZoigvOdmuejKmGj744AMSEhLKhucGOP7447nhhhsAeOGFFzjnnHMYPnw4I0aMoKCggHHjxtGnTx8GDRrE8uXLAZg8eTJ//etfy/bRu3dvcnNzyc3NpWfPnlx11VX06tWL0aNH88MPPwCuI13fvn3p27cvjz32WIUxPvzww6Snp9OnTx8uuugicnNzeeKJJ3jwwQfJyMhgwYIFvPnmm5x00kn069ePkSNHsmXLlqDltm3bxvnnn8+AAQMYMGAAn3zyyRHHKy4u5rbbbmPAgAH06dOHJ598EnBJZ9iwYVxwwQVlY1CVXqeTk5PD0KFDyczMZMyYMWzevBlw07refPPNZGVl8dBDD7F48WL69OlDRkYGt912W1ktasiQISxbtqwshlNPPZXPP//8qN/Pw1Q0tke03mo01pOq6rRpbrwnb5waY6JF+fF7Jk1SnTPHLRcVufUPPnDrBw649Y8+cut797r1Tz5x67t2ufVFi9x6QUHlx3/ooYf05ptvrvDx559/Xtu3b6/5+fmqqnr99dfr5MmTVVV17ty52rdvX1VV/f3vf6/3339/2fN69eqlGzdu1I0bN2pcXJwuXbpUVVUvvPBC/ec//6mqbmypDz/8UFVVb731Vu3Vq1fQGNq1a6cHDhxQVdUdO3YEPV5BQYGWlJSoqurTTz+tv/71r4OWu/jii3XBggWqqvr1119rjx49jjjek08+qffcc4+qqh44cEAzMzN1w4YNOm/ePE1JSdFNmzZpcXGxDho0SBcsWKCFhYV68skn69atW1VVddq0aXr55Zerqhu36tprrz3sdVm4cKGqqt5xxx1lf/MLL7ygN910k6qqrlu3ToN9Jx7tWE82cVF5pZ3u9u6FKg4TYIw50nXXXcfHH39MQkJC2axwo0aNomXLlgB8/PHHvPbaawAMHz6c/Px8dlfSPtipU6eymecyMzPJzc1l586d7Ny5kyFDhgDwP//zP7zzzjtBn9+nTx8mTJjAuHHjyqZrLS8vL4/x48ezefNmCgsLK5xvYs6cOaxe/eOIQ7t372bv3r00LR0zDpg9ezbLly9n+vTpAOzatYv169eTkJDAwIED6dChAwAZGRnk5uaWTfg0atQowNVI2rVrV7a/8ePHA7Bz50727NnDySefDMAll1zCW2+9BcCFF17IPffcw/33389zzz1XK73TLVGUFzgwoCUKE8WmTPlxOT7+8PXExMPXmzQ5fD0l5fD1Fi0qP16vXr3KvvgBHnvsMbZv305WVlbAcZpUup/4+HhKSkrK1gMnFUpMTCxbjouLKzv1VJHLL7+cpUuXcuyxxzJr1izefvttPvroI958803+9Kc/sWLFiiOec8MNN/DrX/+ac845h/nz5zN58uSg+y4pKeHTTz89YkKlQKrKI488wpgxYw7bPn/+/CP+lkOHDqGq9OrVi//+979B91eV169x48aMGjWKN954g1dffTXk+FZVZW0U5aWkuHtrpzDmqAwfPpwDBw7w+OOPl23bv39/heUHDx7MSy+9BLgvztatW5OSkkJaWhpLliwBYMmSJWzcuDHkcZs3b07z5s3L5pMo3SfA888/z7Jly5g1axYlJSVs2rSJ0047jfvuu49du3axd+9ekpOT2RPw/75r1y7at28PwIsvvli2vXy50aNH88gjj5StB7YLlBozZgyPP/44RUVFAHzxxRfsCzHfTffu3dm2bVtZoigqKmLVqlVB/+bk5GQWLVoEwLRp0w57/Morr+TGG29kwIABtKhKlq+EJYrybKhxY6pFRHj99df58MMP6dSpEwMHDmTixIncd1/w2QEmT55MTk4Offr0YdKkSWVfyueffz4FBQX06tWLRx99tEpDjD///PNcd911ZGRklDUKl1dcXMzPf/5zTjzxRPr168eNN95I8+bNOfvss5kxY0ZZI/XkyZO58MILyczMpHXr1mXPL1/u4YcfJjs7mz59+pCens4TTzxxxDGvvPJK0tPT6d+/P7179+aXv/xlyCuWEhISmD59OnfccQd9+/YlIyOjwiutnn32Wa66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\n",
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Created with matplotlib (https://matplotlib.org/) -->\n",
"<svg height=\"262.19625pt\" version=\"1.1\" viewBox=\"0 0 394.160937 262.19625\" width=\"394.160937pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
" <metadata>\n",
" <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
" <cc:Work>\n",
" <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
" <dc:date>2021-01-09T15:26:42.336203</dc:date>\n",
" <dc:format>image/svg+xml</dc:format>\n",
" <dc:creator>\n",
" <cc:Agent>\n",
" <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\n",
" </cc:Agent>\n",
" </dc:creator>\n",
" </cc:Work>\n",
" </rdf:RDF>\n",
" </metadata>\n",
" <defs>\n",
" <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n",
" </defs>\n",
" <g id=\"figure_1\">\n",
" <g id=\"patch_1\">\n",
" <path d=\"M 0 262.19625 \n",
"L 394.160937 262.19625 \n",
"L 394.160937 0 \n",
"L 0 0 \n",
"z\n",
"\" style=\"fill:none;\"/>\n",
" </g>\n",
" <g id=\"axes_1\">\n",
" <g id=\"patch_2\">\n",
" <path d=\"M 52.160938 224.64 \n",
"L 386.960938 224.64 \n",
"L 386.960938 7.2 \n",
"L 52.160938 7.2 \n",
"z\n",
"\" style=\"fill:#ffffff;\"/>\n",
" </g>\n",
" <g id=\"matplotlib.axis_1\">\n",
" <g id=\"xtick_1\">\n",
" <g id=\"line2d_1\">\n",
" <defs>\n",
" <path d=\"M 0 0 \n",
"L 0 3.5 \n",
"\" id=\"mb15aed2d89\" style=\"stroke:#000000;stroke-width:0.8;\"/>\n",
" </defs>\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"64.304739\" xlink:href=\"#mb15aed2d89\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_1\">\n",
" <!-- 0 -->\n",
" <g transform=\"translate(61.123489 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 31.78125 66.40625 \n",
"Q 24.171875 66.40625 20.328125 58.90625 \n",
"Q 16.5 51.421875 16.5 36.375 \n",
"Q 16.5 21.390625 20.328125 13.890625 \n",
"Q 24.171875 6.390625 31.78125 6.390625 \n",
"Q 39.453125 6.390625 43.28125 13.890625 \n",
"Q 47.125 21.390625 47.125 36.375 \n",
"Q 47.125 51.421875 43.28125 58.90625 \n",
"Q 39.453125 66.40625 31.78125 66.40625 \n",
"z\n",
"M 31.78125 74.21875 \n",
"Q 44.046875 74.21875 50.515625 64.515625 \n",
"Q 56.984375 54.828125 56.984375 36.375 \n",
"Q 56.984375 17.96875 50.515625 8.265625 \n",
"Q 44.046875 -1.421875 31.78125 -1.421875 \n",
"Q 19.53125 -1.421875 13.0625 8.265625 \n",
"Q 6.59375 17.96875 6.59375 36.375 \n",
"Q 6.59375 54.828125 13.0625 64.515625 \n",
"Q 19.53125 74.21875 31.78125 74.21875 \n",
"z\n",
"\" id=\"DejaVuSans-48\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_2\">\n",
" <g id=\"line2d_2\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"125.792342\" xlink:href=\"#mb15aed2d89\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_2\">\n",
" <!-- 20 -->\n",
" <g transform=\"translate(119.429842 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 19.1875 8.296875 \n",
"L 53.609375 8.296875 \n",
"L 53.609375 0 \n",
"L 7.328125 0 \n",
"L 7.328125 8.296875 \n",
"Q 12.9375 14.109375 22.625 23.890625 \n",
"Q 32.328125 33.6875 34.8125 36.53125 \n",
"Q 39.546875 41.84375 41.421875 45.53125 \n",
"Q 43.3125 49.21875 43.3125 52.78125 \n",
"Q 43.3125 58.59375 39.234375 62.25 \n",
"Q 35.15625 65.921875 28.609375 65.921875 \n",
"Q 23.96875 65.921875 18.8125 64.3125 \n",
"Q 13.671875 62.703125 7.8125 59.421875 \n",
"L 7.8125 69.390625 \n",
"Q 13.765625 71.78125 18.9375 73 \n",
"Q 24.125 74.21875 28.421875 74.21875 \n",
"Q 39.75 74.21875 46.484375 68.546875 \n",
"Q 53.21875 62.890625 53.21875 53.421875 \n",
"Q 53.21875 48.921875 51.53125 44.890625 \n",
"Q 49.859375 40.875 45.40625 35.40625 \n",
"Q 44.1875 33.984375 37.640625 27.21875 \n",
"Q 31.109375 20.453125 19.1875 8.296875 \n",
"z\n",
"\" id=\"DejaVuSans-50\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-50\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_3\">\n",
" <g id=\"line2d_3\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"187.279946\" xlink:href=\"#mb15aed2d89\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_3\">\n",
" <!-- 40 -->\n",
" <g transform=\"translate(180.917446 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 37.796875 64.3125 \n",
"L 12.890625 25.390625 \n",
"L 37.796875 25.390625 \n",
"z\n",
"M 35.203125 72.90625 \n",
"L 47.609375 72.90625 \n",
"L 47.609375 25.390625 \n",
"L 58.015625 25.390625 \n",
"L 58.015625 17.1875 \n",
"L 47.609375 17.1875 \n",
"L 47.609375 0 \n",
"L 37.796875 0 \n",
"L 37.796875 17.1875 \n",
"L 4.890625 17.1875 \n",
"L 4.890625 26.703125 \n",
"z\n",
"\" id=\"DejaVuSans-52\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-52\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_4\">\n",
" <g id=\"line2d_4\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"248.767549\" xlink:href=\"#mb15aed2d89\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_4\">\n",
" <!-- 60 -->\n",
" <g transform=\"translate(242.405049 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 33.015625 40.375 \n",
"Q 26.375 40.375 22.484375 35.828125 \n",
"Q 18.609375 31.296875 18.609375 23.390625 \n",
"Q 18.609375 15.53125 22.484375 10.953125 \n",
"Q 26.375 6.390625 33.015625 6.390625 \n",
"Q 39.65625 6.390625 43.53125 10.953125 \n",
"Q 47.40625 15.53125 47.40625 23.390625 \n",
"Q 47.40625 31.296875 43.53125 35.828125 \n",
"Q 39.65625 40.375 33.015625 40.375 \n",
"z\n",
"M 52.59375 71.296875 \n",
"L 52.59375 62.3125 \n",
"Q 48.875 64.0625 45.09375 64.984375 \n",
"Q 41.3125 65.921875 37.59375 65.921875 \n",
"Q 27.828125 65.921875 22.671875 59.328125 \n",
"Q 17.53125 52.734375 16.796875 39.40625 \n",
"Q 19.671875 43.65625 24.015625 45.921875 \n",
"Q 28.375 48.1875 33.59375 48.1875 \n",
"Q 44.578125 48.1875 50.953125 41.515625 \n",
"Q 57.328125 34.859375 57.328125 23.390625 \n",
"Q 57.328125 12.15625 50.6875 5.359375 \n",
"Q 44.046875 -1.421875 33.015625 -1.421875 \n",
"Q 20.359375 -1.421875 13.671875 8.265625 \n",
"Q 6.984375 17.96875 6.984375 36.375 \n",
"Q 6.984375 53.65625 15.1875 63.9375 \n",
"Q 23.390625 74.21875 37.203125 74.21875 \n",
"Q 40.921875 74.21875 44.703125 73.484375 \n",
"Q 48.484375 72.75 52.59375 71.296875 \n",
"z\n",
"\" id=\"DejaVuSans-54\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-54\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_5\">\n",
" <g id=\"line2d_5\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"310.255152\" xlink:href=\"#mb15aed2d89\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_5\">\n",
" <!-- 80 -->\n",
" <g transform=\"translate(303.892652 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 31.78125 34.625 \n",
"Q 24.75 34.625 20.71875 30.859375 \n",
"Q 16.703125 27.09375 16.703125 20.515625 \n",
"Q 16.703125 13.921875 20.71875 10.15625 \n",
"Q 24.75 6.390625 31.78125 6.390625 \n",
"Q 38.8125 6.390625 42.859375 10.171875 \n",
"Q 46.921875 13.96875 46.921875 20.515625 \n",
"Q 46.921875 27.09375 42.890625 30.859375 \n",
"Q 38.875 34.625 31.78125 34.625 \n",
"z\n",
"M 21.921875 38.8125 \n",
"Q 15.578125 40.375 12.03125 44.71875 \n",
"Q 8.5 49.078125 8.5 55.328125 \n",
"Q 8.5 64.0625 14.71875 69.140625 \n",
"Q 20.953125 74.21875 31.78125 74.21875 \n",
"Q 42.671875 74.21875 48.875 69.140625 \n",
"Q 55.078125 64.0625 55.078125 55.328125 \n",
"Q 55.078125 49.078125 51.53125 44.71875 \n",
"Q 48 40.375 41.703125 38.8125 \n",
"Q 48.828125 37.15625 52.796875 32.3125 \n",
"Q 56.78125 27.484375 56.78125 20.515625 \n",
"Q 56.78125 9.90625 50.3125 4.234375 \n",
"Q 43.84375 -1.421875 31.78125 -1.421875 \n",
"Q 19.734375 -1.421875 13.25 4.234375 \n",
"Q 6.78125 9.90625 6.78125 20.515625 \n",
"Q 6.78125 27.484375 10.78125 32.3125 \n",
"Q 14.796875 37.15625 21.921875 38.8125 \n",
"z\n",
"M 18.3125 54.390625 \n",
"Q 18.3125 48.734375 21.84375 45.5625 \n",
"Q 25.390625 42.390625 31.78125 42.390625 \n",
"Q 38.140625 42.390625 41.71875 45.5625 \n",
"Q 45.3125 48.734375 45.3125 54.390625 \n",
"Q 45.3125 60.0625 41.71875 63.234375 \n",
"Q 38.140625 66.40625 31.78125 66.40625 \n",
"Q 25.390625 66.40625 21.84375 63.234375 \n",
"Q 18.3125 60.0625 18.3125 54.390625 \n",
"z\n",
"\" id=\"DejaVuSans-56\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-56\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"xtick_6\">\n",
" <g id=\"line2d_6\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"371.742756\" xlink:href=\"#mb15aed2d89\" y=\"224.64\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_6\">\n",
" <!-- 100 -->\n",
" <g transform=\"translate(362.199006 239.238437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 12.40625 8.296875 \n",
"L 28.515625 8.296875 \n",
"L 28.515625 63.921875 \n",
"L 10.984375 60.40625 \n",
"L 10.984375 69.390625 \n",
"L 28.421875 72.90625 \n",
"L 38.28125 72.90625 \n",
"L 38.28125 8.296875 \n",
"L 54.390625 8.296875 \n",
"L 54.390625 0 \n",
"L 12.40625 0 \n",
"z\n",
"\" id=\"DejaVuSans-49\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"127.246094\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_7\">\n",
" <!-- Number of iteration -->\n",
" <g transform=\"translate(170.354688 252.916562)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 9.8125 72.90625 \n",
"L 23.09375 72.90625 \n",
"L 55.421875 11.921875 \n",
"L 55.421875 72.90625 \n",
"L 64.984375 72.90625 \n",
"L 64.984375 0 \n",
"L 51.703125 0 \n",
"L 19.390625 60.984375 \n",
"L 19.390625 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-78\"/>\n",
" <path d=\"M 8.5 21.578125 \n",
"L 8.5 54.6875 \n",
"L 17.484375 54.6875 \n",
"L 17.484375 21.921875 \n",
"Q 17.484375 14.15625 20.5 10.265625 \n",
"Q 23.53125 6.390625 29.59375 6.390625 \n",
"Q 36.859375 6.390625 41.078125 11.03125 \n",
"Q 45.3125 15.671875 45.3125 23.6875 \n",
"L 45.3125 54.6875 \n",
"L 54.296875 54.6875 \n",
"L 54.296875 0 \n",
"L 45.3125 0 \n",
"L 45.3125 8.40625 \n",
"Q 42.046875 3.421875 37.71875 1 \n",
"Q 33.40625 -1.421875 27.6875 -1.421875 \n",
"Q 18.265625 -1.421875 13.375 4.4375 \n",
"Q 8.5 10.296875 8.5 21.578125 \n",
"z\n",
"M 31.109375 56 \n",
"z\n",
"\" id=\"DejaVuSans-117\"/>\n",
" <path d=\"M 52 44.1875 \n",
"Q 55.375 50.25 60.0625 53.125 \n",
"Q 64.75 56 71.09375 56 \n",
"Q 79.640625 56 84.28125 50.015625 \n",
"Q 88.921875 44.046875 88.921875 33.015625 \n",
"L 88.921875 0 \n",
"L 79.890625 0 \n",
"L 79.890625 32.71875 \n",
"Q 79.890625 40.578125 77.09375 44.375 \n",
"Q 74.3125 48.1875 68.609375 48.1875 \n",
"Q 61.625 48.1875 57.5625 43.546875 \n",
"Q 53.515625 38.921875 53.515625 30.90625 \n",
"L 53.515625 0 \n",
"L 44.484375 0 \n",
"L 44.484375 32.71875 \n",
"Q 44.484375 40.625 41.703125 44.40625 \n",
"Q 38.921875 48.1875 33.109375 48.1875 \n",
"Q 26.21875 48.1875 22.15625 43.53125 \n",
"Q 18.109375 38.875 18.109375 30.90625 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 54.6875 \n",
"L 18.109375 54.6875 \n",
"L 18.109375 46.1875 \n",
"Q 21.1875 51.21875 25.484375 53.609375 \n",
"Q 29.78125 56 35.6875 56 \n",
"Q 41.65625 56 45.828125 52.96875 \n",
"Q 50 49.953125 52 44.1875 \n",
"z\n",
"\" id=\"DejaVuSans-109\"/>\n",
" <path d=\"M 48.6875 27.296875 \n",
"Q 48.6875 37.203125 44.609375 42.84375 \n",
"Q 40.53125 48.484375 33.40625 48.484375 \n",
"Q 26.265625 48.484375 22.1875 42.84375 \n",
"Q 18.109375 37.203125 18.109375 27.296875 \n",
"Q 18.109375 17.390625 22.1875 11.75 \n",
"Q 26.265625 6.109375 33.40625 6.109375 \n",
"Q 40.53125 6.109375 44.609375 11.75 \n",
"Q 48.6875 17.390625 48.6875 27.296875 \n",
"z\n",
"M 18.109375 46.390625 \n",
"Q 20.953125 51.265625 25.265625 53.625 \n",
"Q 29.59375 56 35.59375 56 \n",
"Q 45.5625 56 51.78125 48.09375 \n",
"Q 58.015625 40.1875 58.015625 27.296875 \n",
"Q 58.015625 14.40625 51.78125 6.484375 \n",
"Q 45.5625 -1.421875 35.59375 -1.421875 \n",
"Q 29.59375 -1.421875 25.265625 0.953125 \n",
"Q 20.953125 3.328125 18.109375 8.203125 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 75.984375 \n",
"L 18.109375 75.984375 \n",
"z\n",
"\" id=\"DejaVuSans-98\"/>\n",
" <path d=\"M 56.203125 29.59375 \n",
"L 56.203125 25.203125 \n",
"L 14.890625 25.203125 \n",
"Q 15.484375 15.921875 20.484375 11.0625 \n",
"Q 25.484375 6.203125 34.421875 6.203125 \n",
"Q 39.59375 6.203125 44.453125 7.46875 \n",
"Q 49.3125 8.734375 54.109375 11.28125 \n",
"L 54.109375 2.78125 \n",
"Q 49.265625 0.734375 44.1875 -0.34375 \n",
"Q 39.109375 -1.421875 33.890625 -1.421875 \n",
"Q 20.796875 -1.421875 13.15625 6.1875 \n",
"Q 5.515625 13.8125 5.515625 26.8125 \n",
"Q 5.515625 40.234375 12.765625 48.109375 \n",
"Q 20.015625 56 32.328125 56 \n",
"Q 43.359375 56 49.78125 48.890625 \n",
"Q 56.203125 41.796875 56.203125 29.59375 \n",
"z\n",
"M 47.21875 32.234375 \n",
"Q 47.125 39.59375 43.09375 43.984375 \n",
"Q 39.0625 48.390625 32.421875 48.390625 \n",
"Q 24.90625 48.390625 20.390625 44.140625 \n",
"Q 15.875 39.890625 15.1875 32.171875 \n",
"z\n",
"\" id=\"DejaVuSans-101\"/>\n",
" <path d=\"M 41.109375 46.296875 \n",
"Q 39.59375 47.171875 37.8125 47.578125 \n",
"Q 36.03125 48 33.890625 48 \n",
"Q 26.265625 48 22.1875 43.046875 \n",
"Q 18.109375 38.09375 18.109375 28.8125 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 54.6875 \n",
"L 18.109375 54.6875 \n",
"L 18.109375 46.1875 \n",
"Q 20.953125 51.171875 25.484375 53.578125 \n",
"Q 30.03125 56 36.53125 56 \n",
"Q 37.453125 56 38.578125 55.875 \n",
"Q 39.703125 55.765625 41.0625 55.515625 \n",
"z\n",
"\" id=\"DejaVuSans-114\"/>\n",
" <path id=\"DejaVuSans-32\"/>\n",
" <path d=\"M 30.609375 48.390625 \n",
"Q 23.390625 48.390625 19.1875 42.75 \n",
"Q 14.984375 37.109375 14.984375 27.296875 \n",
"Q 14.984375 17.484375 19.15625 11.84375 \n",
"Q 23.34375 6.203125 30.609375 6.203125 \n",
"Q 37.796875 6.203125 41.984375 11.859375 \n",
"Q 46.1875 17.53125 46.1875 27.296875 \n",
"Q 46.1875 37.015625 41.984375 42.703125 \n",
"Q 37.796875 48.390625 30.609375 48.390625 \n",
"z\n",
"M 30.609375 56 \n",
"Q 42.328125 56 49.015625 48.375 \n",
"Q 55.71875 40.765625 55.71875 27.296875 \n",
"Q 55.71875 13.875 49.015625 6.21875 \n",
"Q 42.328125 -1.421875 30.609375 -1.421875 \n",
"Q 18.84375 -1.421875 12.171875 6.21875 \n",
"Q 5.515625 13.875 5.515625 27.296875 \n",
"Q 5.515625 40.765625 12.171875 48.375 \n",
"Q 18.84375 56 30.609375 56 \n",
"z\n",
"\" id=\"DejaVuSans-111\"/>\n",
" <path d=\"M 37.109375 75.984375 \n",
"L 37.109375 68.5 \n",
"L 28.515625 68.5 \n",
"Q 23.6875 68.5 21.796875 66.546875 \n",
"Q 19.921875 64.59375 19.921875 59.515625 \n",
"L 19.921875 54.6875 \n",
"L 34.71875 54.6875 \n",
"L 34.71875 47.703125 \n",
"L 19.921875 47.703125 \n",
"L 19.921875 0 \n",
"L 10.890625 0 \n",
"L 10.890625 47.703125 \n",
"L 2.296875 47.703125 \n",
"L 2.296875 54.6875 \n",
"L 10.890625 54.6875 \n",
"L 10.890625 58.5 \n",
"Q 10.890625 67.625 15.140625 71.796875 \n",
"Q 19.390625 75.984375 28.609375 75.984375 \n",
"z\n",
"\" id=\"DejaVuSans-102\"/>\n",
" <path d=\"M 9.421875 54.6875 \n",
"L 18.40625 54.6875 \n",
"L 18.40625 0 \n",
"L 9.421875 0 \n",
"z\n",
"M 9.421875 75.984375 \n",
"L 18.40625 75.984375 \n",
"L 18.40625 64.59375 \n",
"L 9.421875 64.59375 \n",
"z\n",
"\" id=\"DejaVuSans-105\"/>\n",
" <path d=\"M 18.3125 70.21875 \n",
"L 18.3125 54.6875 \n",
"L 36.8125 54.6875 \n",
"L 36.8125 47.703125 \n",
"L 18.3125 47.703125 \n",
"L 18.3125 18.015625 \n",
"Q 18.3125 11.328125 20.140625 9.421875 \n",
"Q 21.96875 7.515625 27.59375 7.515625 \n",
"L 36.8125 7.515625 \n",
"L 36.8125 0 \n",
"L 27.59375 0 \n",
"Q 17.1875 0 13.234375 3.875 \n",
"Q 9.28125 7.765625 9.28125 18.015625 \n",
"L 9.28125 47.703125 \n",
"L 2.6875 47.703125 \n",
"L 2.6875 54.6875 \n",
"L 9.28125 54.6875 \n",
"L 9.28125 70.21875 \n",
"z\n",
"\" id=\"DejaVuSans-116\"/>\n",
" <path d=\"M 34.28125 27.484375 \n",
"Q 23.390625 27.484375 19.1875 25 \n",
"Q 14.984375 22.515625 14.984375 16.5 \n",
"Q 14.984375 11.71875 18.140625 8.90625 \n",
"Q 21.296875 6.109375 26.703125 6.109375 \n",
"Q 34.1875 6.109375 38.703125 11.40625 \n",
"Q 43.21875 16.703125 43.21875 25.484375 \n",
"L 43.21875 27.484375 \n",
"z\n",
"M 52.203125 31.203125 \n",
"L 52.203125 0 \n",
"L 43.21875 0 \n",
"L 43.21875 8.296875 \n",
"Q 40.140625 3.328125 35.546875 0.953125 \n",
"Q 30.953125 -1.421875 24.3125 -1.421875 \n",
"Q 15.921875 -1.421875 10.953125 3.296875 \n",
"Q 6 8.015625 6 15.921875 \n",
"Q 6 25.140625 12.171875 29.828125 \n",
"Q 18.359375 34.515625 30.609375 34.515625 \n",
"L 43.21875 34.515625 \n",
"L 43.21875 35.40625 \n",
"Q 43.21875 41.609375 39.140625 45 \n",
"Q 35.0625 48.390625 27.6875 48.390625 \n",
"Q 23 48.390625 18.546875 47.265625 \n",
"Q 14.109375 46.140625 10.015625 43.890625 \n",
"L 10.015625 52.203125 \n",
"Q 14.9375 54.109375 19.578125 55.046875 \n",
"Q 24.21875 56 28.609375 56 \n",
"Q 40.484375 56 46.34375 49.84375 \n",
"Q 52.203125 43.703125 52.203125 31.203125 \n",
"z\n",
"\" id=\"DejaVuSans-97\"/>\n",
" <path d=\"M 54.890625 33.015625 \n",
"L 54.890625 0 \n",
"L 45.90625 0 \n",
"L 45.90625 32.71875 \n",
"Q 45.90625 40.484375 42.875 44.328125 \n",
"Q 39.84375 48.1875 33.796875 48.1875 \n",
"Q 26.515625 48.1875 22.3125 43.546875 \n",
"Q 18.109375 38.921875 18.109375 30.90625 \n",
"L 18.109375 0 \n",
"L 9.078125 0 \n",
"L 9.078125 54.6875 \n",
"L 18.109375 54.6875 \n",
"L 18.109375 46.1875 \n",
"Q 21.34375 51.125 25.703125 53.5625 \n",
"Q 30.078125 56 35.796875 56 \n",
"Q 45.21875 56 50.046875 50.171875 \n",
"Q 54.890625 44.34375 54.890625 33.015625 \n",
"z\n",
"\" id=\"DejaVuSans-110\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-78\"/>\n",
" <use x=\"74.804688\" xlink:href=\"#DejaVuSans-117\"/>\n",
" <use x=\"138.183594\" xlink:href=\"#DejaVuSans-109\"/>\n",
" <use x=\"235.595703\" xlink:href=\"#DejaVuSans-98\"/>\n",
" <use x=\"299.072266\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"360.595703\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"401.708984\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"433.496094\" xlink:href=\"#DejaVuSans-111\"/>\n",
" <use x=\"494.677734\" xlink:href=\"#DejaVuSans-102\"/>\n",
" <use x=\"529.882812\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"561.669922\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"589.453125\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"628.662109\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"690.185547\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"731.298828\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"792.578125\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"831.787109\" xlink:href=\"#DejaVuSans-105\"/>\n",
" <use x=\"859.570312\" xlink:href=\"#DejaVuSans-111\"/>\n",
" <use x=\"920.751953\" xlink:href=\"#DejaVuSans-110\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"matplotlib.axis_2\">\n",
" <g id=\"ytick_1\">\n",
" <g id=\"line2d_7\">\n",
" <defs>\n",
" <path d=\"M 0 0 \n",
"L -3.5 0 \n",
"\" id=\"m82ff1f3097\" style=\"stroke:#000000;stroke-width:0.8;\"/>\n",
" </defs>\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m82ff1f3097\" y=\"183.328577\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_8\">\n",
" <!-- −1.0 -->\n",
" <g transform=\"translate(20.878125 187.127796)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 10.59375 35.5 \n",
"L 73.1875 35.5 \n",
"L 73.1875 27.203125 \n",
"L 10.59375 27.203125 \n",
"z\n",
"\" id=\"DejaVuSans-8722\"/>\n",
" <path d=\"M 10.6875 12.40625 \n",
"L 21 12.40625 \n",
"L 21 0 \n",
"L 10.6875 0 \n",
"z\n",
"\" id=\"DejaVuSans-46\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-49\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-48\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_2\">\n",
" <g id=\"line2d_8\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m82ff1f3097\" y=\"137.175537\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_9\">\n",
" <!-- −0.8 -->\n",
" <g transform=\"translate(20.878125 140.974756)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-56\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_3\">\n",
" <g id=\"line2d_9\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m82ff1f3097\" y=\"91.022497\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_10\">\n",
" <!-- −0.6 -->\n",
" <g transform=\"translate(20.878125 94.821716)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-54\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"ytick_4\">\n",
" <g id=\"line2d_10\">\n",
" <g>\n",
" <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"52.160938\" xlink:href=\"#m82ff1f3097\" y=\"44.869457\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_11\">\n",
" <!-- −0.4 -->\n",
" <g transform=\"translate(20.878125 48.668676)scale(0.1 -0.1)\">\n",
" <use xlink:href=\"#DejaVuSans-8722\"/>\n",
" <use x=\"83.789062\" xlink:href=\"#DejaVuSans-48\"/>\n",
" <use x=\"147.412109\" xlink:href=\"#DejaVuSans-46\"/>\n",
" <use x=\"179.199219\" xlink:href=\"#DejaVuSans-52\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"text_12\">\n",
" <!-- Energy (Ha) -->\n",
" <g transform=\"translate(14.798437 145.741094)rotate(-90)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 9.8125 72.90625 \n",
"L 55.90625 72.90625 \n",
"L 55.90625 64.59375 \n",
"L 19.671875 64.59375 \n",
"L 19.671875 43.015625 \n",
"L 54.390625 43.015625 \n",
"L 54.390625 34.71875 \n",
"L 19.671875 34.71875 \n",
"L 19.671875 8.296875 \n",
"L 56.78125 8.296875 \n",
"L 56.78125 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-69\"/>\n",
" <path d=\"M 45.40625 27.984375 \n",
"Q 45.40625 37.75 41.375 43.109375 \n",
"Q 37.359375 48.484375 30.078125 48.484375 \n",
"Q 22.859375 48.484375 18.828125 43.109375 \n",
"Q 14.796875 37.75 14.796875 27.984375 \n",
"Q 14.796875 18.265625 18.828125 12.890625 \n",
"Q 22.859375 7.515625 30.078125 7.515625 \n",
"Q 37.359375 7.515625 41.375 12.890625 \n",
"Q 45.40625 18.265625 45.40625 27.984375 \n",
"z\n",
"M 54.390625 6.78125 \n",
"Q 54.390625 -7.171875 48.1875 -13.984375 \n",
"Q 42 -20.796875 29.203125 -20.796875 \n",
"Q 24.46875 -20.796875 20.265625 -20.09375 \n",
"Q 16.0625 -19.390625 12.109375 -17.921875 \n",
"L 12.109375 -9.1875 \n",
"Q 16.0625 -11.328125 19.921875 -12.34375 \n",
"Q 23.78125 -13.375 27.78125 -13.375 \n",
"Q 36.625 -13.375 41.015625 -8.765625 \n",
"Q 45.40625 -4.15625 45.40625 5.171875 \n",
"L 45.40625 9.625 \n",
"Q 42.625 4.78125 38.28125 2.390625 \n",
"Q 33.9375 0 27.875 0 \n",
"Q 17.828125 0 11.671875 7.65625 \n",
"Q 5.515625 15.328125 5.515625 27.984375 \n",
"Q 5.515625 40.671875 11.671875 48.328125 \n",
"Q 17.828125 56 27.875 56 \n",
"Q 33.9375 56 38.28125 53.609375 \n",
"Q 42.625 51.21875 45.40625 46.390625 \n",
"L 45.40625 54.6875 \n",
"L 54.390625 54.6875 \n",
"z\n",
"\" id=\"DejaVuSans-103\"/>\n",
" <path d=\"M 32.171875 -5.078125 \n",
"Q 28.375 -14.84375 24.75 -17.8125 \n",
"Q 21.140625 -20.796875 15.09375 -20.796875 \n",
"L 7.90625 -20.796875 \n",
"L 7.90625 -13.28125 \n",
"L 13.1875 -13.28125 \n",
"Q 16.890625 -13.28125 18.9375 -11.515625 \n",
"Q 21 -9.765625 23.484375 -3.21875 \n",
"L 25.09375 0.875 \n",
"L 2.984375 54.6875 \n",
"L 12.5 54.6875 \n",
"L 29.59375 11.921875 \n",
"L 46.6875 54.6875 \n",
"L 56.203125 54.6875 \n",
"z\n",
"\" id=\"DejaVuSans-121\"/>\n",
" <path d=\"M 31 75.875 \n",
"Q 24.46875 64.65625 21.28125 53.65625 \n",
"Q 18.109375 42.671875 18.109375 31.390625 \n",
"Q 18.109375 20.125 21.3125 9.0625 \n",
"Q 24.515625 -2 31 -13.1875 \n",
"L 23.1875 -13.1875 \n",
"Q 15.875 -1.703125 12.234375 9.375 \n",
"Q 8.59375 20.453125 8.59375 31.390625 \n",
"Q 8.59375 42.28125 12.203125 53.3125 \n",
"Q 15.828125 64.359375 23.1875 75.875 \n",
"z\n",
"\" id=\"DejaVuSans-40\"/>\n",
" <path d=\"M 9.8125 72.90625 \n",
"L 19.671875 72.90625 \n",
"L 19.671875 43.015625 \n",
"L 55.515625 43.015625 \n",
"L 55.515625 72.90625 \n",
"L 65.375 72.90625 \n",
"L 65.375 0 \n",
"L 55.515625 0 \n",
"L 55.515625 34.71875 \n",
"L 19.671875 34.71875 \n",
"L 19.671875 0 \n",
"L 9.8125 0 \n",
"z\n",
"\" id=\"DejaVuSans-72\"/>\n",
" <path d=\"M 8.015625 75.875 \n",
"L 15.828125 75.875 \n",
"Q 23.140625 64.359375 26.78125 53.3125 \n",
"Q 30.421875 42.28125 30.421875 31.390625 \n",
"Q 30.421875 20.453125 26.78125 9.375 \n",
"Q 23.140625 -1.703125 15.828125 -13.1875 \n",
"L 8.015625 -13.1875 \n",
"Q 14.5 -2 17.703125 9.0625 \n",
"Q 20.90625 20.125 20.90625 31.390625 \n",
"Q 20.90625 42.671875 17.703125 53.65625 \n",
"Q 14.5 64.65625 8.015625 75.875 \n",
"z\n",
"\" id=\"DejaVuSans-41\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-69\"/>\n",
" <use x=\"63.183594\" xlink:href=\"#DejaVuSans-110\"/>\n",
" <use x=\"126.5625\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"188.085938\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"227.449219\" xlink:href=\"#DejaVuSans-103\"/>\n",
" <use x=\"290.925781\" xlink:href=\"#DejaVuSans-121\"/>\n",
" <use x=\"350.105469\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"381.892578\" xlink:href=\"#DejaVuSans-40\"/>\n",
" <use x=\"420.90625\" xlink:href=\"#DejaVuSans-72\"/>\n",
" <use x=\"496.101562\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"557.380859\" xlink:href=\"#DejaVuSans-41\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g id=\"line2d_11\">\n",
" <path clip-path=\"url(#pd4f85b6dad)\" d=\"M 67.379119 17.083636 \n",
"L 70.453499 52.067317 \n",
"L 73.52788 73.893781 \n",
"L 76.60226 89.403365 \n",
"L 79.67664 101.103015 \n",
"L 82.75102 106.747158 \n",
"L 85.8254 106.460241 \n",
"L 88.89978 105.507185 \n",
"L 91.974161 108.730875 \n",
"L 95.048541 114.828986 \n",
"L 98.122921 121.317281 \n",
"L 101.197301 127.271118 \n",
"L 104.271681 132.722947 \n",
"L 107.346061 136.290317 \n",
"L 110.420442 136.491529 \n",
"L 113.494822 135.229009 \n",
"L 116.569202 136.040872 \n",
"L 119.643582 139.270694 \n",
"L 122.717962 143.632285 \n",
"L 125.792342 149.250196 \n",
"L 128.866723 156.475322 \n",
"L 131.941103 164.321024 \n",
"L 135.015483 171.975289 \n",
"L 138.089863 180.051056 \n",
"L 141.164243 188.816374 \n",
"L 144.238623 196.68898 \n",
"L 147.313004 201.880479 \n",
"L 150.387384 204.341765 \n",
"L 153.461764 205.809501 \n",
"L 156.536144 207.470168 \n",
"L 159.610524 208.717602 \n",
"L 162.684904 208.33442 \n",
"L 165.759285 206.106599 \n",
"L 168.833665 203.368367 \n",
"L 171.908045 202.193985 \n",
"L 174.982425 203.821426 \n",
"L 178.056805 207.6248 \n",
"L 181.131185 211.442128 \n",
"L 184.205566 213.178232 \n",
"L 187.279946 212.501548 \n",
"L 190.354326 210.881746 \n",
"L 193.428706 209.83521 \n",
"L 196.503086 209.713236 \n",
"L 199.577466 210.116092 \n",
"L 202.651847 210.667376 \n",
"L 205.726227 211.253538 \n",
"L 208.800607 211.874728 \n",
"L 211.874987 212.461954 \n",
"L 214.949367 212.89122 \n",
"L 218.023747 213.121225 \n",
"L 221.098128 213.196632 \n",
"L 224.172508 213.159061 \n",
"L 227.246888 213.040632 \n",
"L 230.321268 212.924493 \n",
"L 233.395648 212.956861 \n",
"L 236.470028 213.213594 \n",
"L 239.544409 213.568351 \n",
"L 242.618789 213.799369 \n",
"L 245.693169 213.844271 \n",
"L 248.767549 213.858923 \n",
"L 251.841929 213.990464 \n",
"L 254.916309 214.191296 \n",
"L 257.99069 214.30897 \n",
"L 261.06507 214.272577 \n",
"L 264.13945 214.151579 \n",
"L 267.21383 214.087872 \n",
"L 270.28821 214.171999 \n",
"L 273.36259 214.356773 \n",
"L 276.436971 214.517026 \n",
"L 279.511351 214.588477 \n",
"L 282.585731 214.597824 \n",
"L 285.660111 214.587599 \n",
"L 288.734491 214.580132 \n",
"L 291.808871 214.588033 \n",
"L 294.883252 214.607926 \n",
"L 297.957632 214.624079 \n",
"L 301.032012 214.635498 \n",
"L 304.106392 214.655124 \n",
"L 307.180772 214.683389 \n",
"L 310.255152 214.704753 \n",
"L 313.329533 214.707474 \n",
"L 316.403913 214.697921 \n",
"L 319.478293 214.695318 \n",
"L 322.552673 214.706996 \n",
"L 325.627053 214.716078 \n",
"L 328.701433 214.708365 \n",
"L 331.775814 214.695788 \n",
"L 334.850194 214.696601 \n",
"L 337.924574 214.71113 \n",
"L 340.998954 214.727622 \n",
"L 344.073334 214.736059 \n",
"L 347.147714 214.734302 \n",
"L 350.222095 214.729354 \n",
"L 353.296475 214.728984 \n",
"L 356.370855 214.732614 \n",
"L 359.445235 214.735857 \n",
"L 362.519615 214.737722 \n",
"L 365.593995 214.739443 \n",
"L 368.668376 214.742204 \n",
"L 371.742756 214.746107 \n",
"\" style=\"fill:none;stroke:#ff0000;stroke-linecap:square;stroke-opacity:0.7;stroke-width:1.5;\"/>\n",
" </g>\n",
" <g id=\"line2d_12\">\n",
" <path clip-path=\"url(#pd4f85b6dad)\" d=\"M 67.379119 214.756364 \n",
"L 70.453499 214.756364 \n",
"L 73.52788 214.756364 \n",
"L 76.60226 214.756364 \n",
"L 79.67664 214.756364 \n",
"L 82.75102 214.756364 \n",
"L 85.8254 214.756364 \n",
"L 88.89978 214.756364 \n",
"L 91.974161 214.756364 \n",
"L 95.048541 214.756364 \n",
"L 98.122921 214.756364 \n",
"L 101.197301 214.756364 \n",
"L 104.271681 214.756364 \n",
"L 107.346061 214.756364 \n",
"L 110.420442 214.756364 \n",
"L 113.494822 214.756364 \n",
"L 116.569202 214.756364 \n",
"L 119.643582 214.756364 \n",
"L 122.717962 214.756364 \n",
"L 125.792342 214.756364 \n",
"L 128.866723 214.756364 \n",
"L 131.941103 214.756364 \n",
"L 135.015483 214.756364 \n",
"L 138.089863 214.756364 \n",
"L 141.164243 214.756364 \n",
"L 144.238623 214.756364 \n",
"L 147.313004 214.756364 \n",
"L 150.387384 214.756364 \n",
"L 153.461764 214.756364 \n",
"L 156.536144 214.756364 \n",
"L 159.610524 214.756364 \n",
"L 162.684904 214.756364 \n",
"L 165.759285 214.756364 \n",
"L 168.833665 214.756364 \n",
"L 171.908045 214.756364 \n",
"L 174.982425 214.756364 \n",
"L 178.056805 214.756364 \n",
"L 181.131185 214.756364 \n",
"L 184.205566 214.756364 \n",
"L 187.279946 214.756364 \n",
"L 190.354326 214.756364 \n",
"L 193.428706 214.756364 \n",
"L 196.503086 214.756364 \n",
"L 199.577466 214.756364 \n",
"L 202.651847 214.756364 \n",
"L 205.726227 214.756364 \n",
"L 208.800607 214.756364 \n",
"L 211.874987 214.756364 \n",
"L 214.949367 214.756364 \n",
"L 218.023747 214.756364 \n",
"L 221.098128 214.756364 \n",
"L 224.172508 214.756364 \n",
"L 227.246888 214.756364 \n",
"L 230.321268 214.756364 \n",
"L 233.395648 214.756364 \n",
"L 236.470028 214.756364 \n",
"L 239.544409 214.756364 \n",
"L 242.618789 214.756364 \n",
"L 245.693169 214.756364 \n",
"L 248.767549 214.756364 \n",
"L 251.841929 214.756364 \n",
"L 254.916309 214.756364 \n",
"L 257.99069 214.756364 \n",
"L 261.06507 214.756364 \n",
"L 264.13945 214.756364 \n",
"L 267.21383 214.756364 \n",
"L 270.28821 214.756364 \n",
"L 273.36259 214.756364 \n",
"L 276.436971 214.756364 \n",
"L 279.511351 214.756364 \n",
"L 282.585731 214.756364 \n",
"L 285.660111 214.756364 \n",
"L 288.734491 214.756364 \n",
"L 291.808871 214.756364 \n",
"L 294.883252 214.756364 \n",
"L 297.957632 214.756364 \n",
"L 301.032012 214.756364 \n",
"L 304.106392 214.756364 \n",
"L 307.180772 214.756364 \n",
"L 310.255152 214.756364 \n",
"L 313.329533 214.756364 \n",
"L 316.403913 214.756364 \n",
"L 319.478293 214.756364 \n",
"L 322.552673 214.756364 \n",
"L 325.627053 214.756364 \n",
"L 328.701433 214.756364 \n",
"L 331.775814 214.756364 \n",
"L 334.850194 214.756364 \n",
"L 337.924574 214.756364 \n",
"L 340.998954 214.756364 \n",
"L 344.073334 214.756364 \n",
"L 347.147714 214.756364 \n",
"L 350.222095 214.756364 \n",
"L 353.296475 214.756364 \n",
"L 356.370855 214.756364 \n",
"L 359.445235 214.756364 \n",
"L 362.519615 214.756364 \n",
"L 365.593995 214.756364 \n",
"L 368.668376 214.756364 \n",
"L 371.742756 214.756364 \n",
"\" style=\"fill:none;stroke:#0000ff;stroke-dasharray:1.5,2.475;stroke-dashoffset:0;stroke-opacity:0.7;stroke-width:1.5;\"/>\n",
" </g>\n",
" <g id=\"patch_3\">\n",
" <path d=\"M 52.160938 224.64 \n",
"L 52.160938 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_4\">\n",
" <path d=\"M 386.960938 224.64 \n",
"L 386.960938 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_5\">\n",
" <path d=\"M 52.160938 224.64 \n",
"L 386.960938 224.64 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"patch_6\">\n",
" <path d=\"M 52.160938 7.2 \n",
"L 386.960938 7.2 \n",
"\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\n",
" </g>\n",
" <g id=\"legend_1\">\n",
" <g id=\"patch_7\">\n",
" <path d=\"M 244.220312 44.978125 \n",
"L 379.960938 44.978125 \n",
"Q 381.960938 44.978125 381.960938 42.978125 \n",
"L 381.960938 14.2 \n",
"Q 381.960938 12.2 379.960938 12.2 \n",
"L 244.220312 12.2 \n",
"Q 242.220312 12.2 242.220312 14.2 \n",
"L 242.220312 42.978125 \n",
"Q 242.220312 44.978125 244.220312 44.978125 \n",
"z\n",
"\" style=\"fill:#ffffff;opacity:0.8;stroke:#cccccc;stroke-linejoin:miter;\"/>\n",
" </g>\n",
" <g id=\"line2d_13\">\n",
" <path d=\"M 246.220312 20.4 \n",
"L 266.220312 20.4 \n",
"\" style=\"fill:none;stroke:#ff0000;stroke-linecap:square;stroke-opacity:0.7;stroke-width:1.5;\"/>\n",
" </g>\n",
" <g id=\"line2d_14\"/>\n",
" <g id=\"text_13\">\n",
" <!-- $\\left\\langle {\\psi \\left( {\\theta } \\right)} \\right|H\\left| {\\psi \\left( {\\theta } \\right)} \\right\\rangle $ -->\n",
" <g transform=\"translate(274.220312 23.9)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 8.9375 31.34375 \n",
"L 22.703125 75.875 \n",
"L 31 75.875 \n",
"L 17.234375 31.34375 \n",
"L 31 -13.1875 \n",
"L 22.703125 -13.1875 \n",
"z\n",
"\" id=\"DejaVuSans-10216\"/>\n",
" <path d=\"M 24.859375 -1.21875 \n",
"Q 13.921875 0.59375 9.625 5.328125 \n",
"Q 4.34375 11.140625 6.640625 23 \n",
"L 12.796875 54.6875 \n",
"L 21.875 54.6875 \n",
"L 15.765625 23.34375 \n",
"Q 14.0625 14.40625 17.484375 10.6875 \n",
"Q 20.515625 7.46875 26.421875 6.78125 \n",
"L 35.6875 54.6875 \n",
"L 44.625 54.6875 \n",
"L 35.359375 6.84375 \n",
"Q 41.890625 7.515625 45.75 10.75 \n",
"Q 50.734375 14.84375 52.390625 23.390625 \n",
"L 58.453125 54.6875 \n",
"L 67.53125 54.6875 \n",
"L 61.375 23.046875 \n",
"Q 58.984375 10.75 51.5625 5.375 \n",
"Q 44.875 0.53125 33.796875 -1.171875 \n",
"L 29.984375 -20.796875 \n",
"L 21.046875 -20.796875 \n",
"z\n",
"\" id=\"DejaVuSans-Oblique-968\"/>\n",
" <path d=\"M 45.515625 34.671875 \n",
"L 14.453125 34.671875 \n",
"Q 12.359375 20.0625 14.5 13.875 \n",
"Q 17.1875 6.25 24.46875 6.25 \n",
"Q 31.78125 6.25 37.359375 13.921875 \n",
"Q 42.234375 20.65625 45.515625 34.671875 \n",
"z\n",
"M 47.015625 42.96875 \n",
"Q 48.34375 56.84375 46.625 61.71875 \n",
"Q 43.953125 69.4375 36.765625 69.4375 \n",
"Q 29.296875 69.4375 23.828125 61.8125 \n",
"Q 19.53125 55.671875 16.15625 42.96875 \n",
"z\n",
"M 38.1875 76.765625 \n",
"Q 49.90625 76.765625 54.59375 66.40625 \n",
"Q 59.28125 56.109375 55.71875 37.84375 \n",
"Q 52.203125 19.625 43.453125 9.28125 \n",
"Q 34.765625 -1.125 23.046875 -1.125 \n",
"Q 11.28125 -1.125 6.640625 9.28125 \n",
"Q 2 19.625 5.515625 37.84375 \n",
"Q 9.078125 56.109375 17.71875 66.40625 \n",
"Q 26.421875 76.765625 38.1875 76.765625 \n",
"z\n",
"\" id=\"DejaVuSans-Oblique-952\"/>\n",
" <path d=\"M 21 76.421875 \n",
"L 21 -23.578125 \n",
"L 12.703125 -23.578125 \n",
"L 12.703125 76.421875 \n",
"z\n",
"\" id=\"DejaVuSans-124\"/>\n",
" <path d=\"M 16.890625 72.90625 \n",
"L 26.8125 72.90625 \n",
"L 21 43.015625 \n",
"L 56.78125 43.015625 \n",
"L 62.59375 72.90625 \n",
"L 72.515625 72.90625 \n",
"L 58.296875 0 \n",
"L 48.390625 0 \n",
"L 55.171875 34.71875 \n",
"L 19.390625 34.71875 \n",
"L 12.59375 0 \n",
"L 2.6875 0 \n",
"z\n",
"\" id=\"DejaVuSans-Oblique-72\"/>\n",
" <path d=\"M 30.078125 31.34375 \n",
"L 16.3125 -13.1875 \n",
"L 8.015625 -13.1875 \n",
"L 21.78125 31.34375 \n",
"L 8.015625 75.875 \n",
"L 16.3125 75.875 \n",
"z\n",
"\" id=\"DejaVuSans-10217\"/>\n",
" </defs>\n",
" <use transform=\"translate(0 0.234375)\" xlink:href=\"#DejaVuSans-10216\"/>\n",
" <use transform=\"translate(39.013672 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-968\"/>\n",
" <use transform=\"translate(104.980469 0.234375)\" xlink:href=\"#DejaVuSans-40\"/>\n",
" <use transform=\"translate(143.994141 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-952\"/>\n",
" <use transform=\"translate(205.175781 0.234375)\" xlink:href=\"#DejaVuSans-41\"/>\n",
" <use transform=\"translate(244.189453 0.234375)\" xlink:href=\"#DejaVuSans-124\"/>\n",
" <use transform=\"translate(277.880859 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-72\"/>\n",
" <use transform=\"translate(353.076172 0.234375)\" xlink:href=\"#DejaVuSans-124\"/>\n",
" <use transform=\"translate(386.767578 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-968\"/>\n",
" <use transform=\"translate(452.734375 0.234375)\" xlink:href=\"#DejaVuSans-40\"/>\n",
" <use transform=\"translate(491.748047 0.234375)\" xlink:href=\"#DejaVuSans-Oblique-952\"/>\n",
" <use transform=\"translate(552.929688 0.234375)\" xlink:href=\"#DejaVuSans-41\"/>\n",
" <use transform=\"translate(591.943359 0.234375)\" xlink:href=\"#DejaVuSans-10217\"/>\n",
" </g>\n",
" </g>\n",
" <g id=\"line2d_15\">\n",
" <path d=\"M 246.220312 35.398437 \n",
"L 266.220312 35.398437 \n",
"\" style=\"fill:none;stroke:#0000ff;stroke-dasharray:1.5,2.475;stroke-dashoffset:0;stroke-opacity:0.7;stroke-width:1.5;\"/>\n",
" </g>\n",
" <g id=\"line2d_16\"/>\n",
" <g id=\"text_14\">\n",
" <!-- Ground-state energy -->\n",
" <g transform=\"translate(274.220312 38.898437)scale(0.1 -0.1)\">\n",
" <defs>\n",
" <path d=\"M 59.515625 10.40625 \n",
"L 59.515625 29.984375 \n",
"L 43.40625 29.984375 \n",
"L 43.40625 38.09375 \n",
"L 69.28125 38.09375 \n",
"L 69.28125 6.78125 \n",
"Q 63.578125 2.734375 56.6875 0.65625 \n",
"Q 49.8125 -1.421875 42 -1.421875 \n",
"Q 24.90625 -1.421875 15.25 8.5625 \n",
"Q 5.609375 18.5625 5.609375 36.375 \n",
"Q 5.609375 54.25 15.25 64.234375 \n",
"Q 24.90625 74.21875 42 74.21875 \n",
"Q 49.125 74.21875 55.546875 72.453125 \n",
"Q 61.96875 70.703125 67.390625 67.28125 \n",
"L 67.390625 56.78125 \n",
"Q 61.921875 61.421875 55.765625 63.765625 \n",
"Q 49.609375 66.109375 42.828125 66.109375 \n",
"Q 29.4375 66.109375 22.71875 58.640625 \n",
"Q 16.015625 51.171875 16.015625 36.375 \n",
"Q 16.015625 21.625 22.71875 14.15625 \n",
"Q 29.4375 6.6875 42.828125 6.6875 \n",
"Q 48.046875 6.6875 52.140625 7.59375 \n",
"Q 56.25 8.5 59.515625 10.40625 \n",
"z\n",
"\" id=\"DejaVuSans-71\"/>\n",
" <path d=\"M 45.40625 46.390625 \n",
"L 45.40625 75.984375 \n",
"L 54.390625 75.984375 \n",
"L 54.390625 0 \n",
"L 45.40625 0 \n",
"L 45.40625 8.203125 \n",
"Q 42.578125 3.328125 38.25 0.953125 \n",
"Q 33.9375 -1.421875 27.875 -1.421875 \n",
"Q 17.96875 -1.421875 11.734375 6.484375 \n",
"Q 5.515625 14.40625 5.515625 27.296875 \n",
"Q 5.515625 40.1875 11.734375 48.09375 \n",
"Q 17.96875 56 27.875 56 \n",
"Q 33.9375 56 38.25 53.625 \n",
"Q 42.578125 51.265625 45.40625 46.390625 \n",
"z\n",
"M 14.796875 27.296875 \n",
"Q 14.796875 17.390625 18.875 11.75 \n",
"Q 22.953125 6.109375 30.078125 6.109375 \n",
"Q 37.203125 6.109375 41.296875 11.75 \n",
"Q 45.40625 17.390625 45.40625 27.296875 \n",
"Q 45.40625 37.203125 41.296875 42.84375 \n",
"Q 37.203125 48.484375 30.078125 48.484375 \n",
"Q 22.953125 48.484375 18.875 42.84375 \n",
"Q 14.796875 37.203125 14.796875 27.296875 \n",
"z\n",
"\" id=\"DejaVuSans-100\"/>\n",
" <path d=\"M 4.890625 31.390625 \n",
"L 31.203125 31.390625 \n",
"L 31.203125 23.390625 \n",
"L 4.890625 23.390625 \n",
"z\n",
"\" id=\"DejaVuSans-45\"/>\n",
" <path d=\"M 44.28125 53.078125 \n",
"L 44.28125 44.578125 \n",
"Q 40.484375 46.53125 36.375 47.5 \n",
"Q 32.28125 48.484375 27.875 48.484375 \n",
"Q 21.1875 48.484375 17.84375 46.4375 \n",
"Q 14.5 44.390625 14.5 40.28125 \n",
"Q 14.5 37.15625 16.890625 35.375 \n",
"Q 19.28125 33.59375 26.515625 31.984375 \n",
"L 29.59375 31.296875 \n",
"Q 39.15625 29.25 43.1875 25.515625 \n",
"Q 47.21875 21.78125 47.21875 15.09375 \n",
"Q 47.21875 7.46875 41.1875 3.015625 \n",
"Q 35.15625 -1.421875 24.609375 -1.421875 \n",
"Q 20.21875 -1.421875 15.453125 -0.5625 \n",
"Q 10.6875 0.296875 5.421875 2 \n",
"L 5.421875 11.28125 \n",
"Q 10.40625 8.6875 15.234375 7.390625 \n",
"Q 20.0625 6.109375 24.8125 6.109375 \n",
"Q 31.15625 6.109375 34.5625 8.28125 \n",
"Q 37.984375 10.453125 37.984375 14.40625 \n",
"Q 37.984375 18.0625 35.515625 20.015625 \n",
"Q 33.0625 21.96875 24.703125 23.78125 \n",
"L 21.578125 24.515625 \n",
"Q 13.234375 26.265625 9.515625 29.90625 \n",
"Q 5.8125 33.546875 5.8125 39.890625 \n",
"Q 5.8125 47.609375 11.28125 51.796875 \n",
"Q 16.75 56 26.8125 56 \n",
"Q 31.78125 56 36.171875 55.265625 \n",
"Q 40.578125 54.546875 44.28125 53.078125 \n",
"z\n",
"\" id=\"DejaVuSans-115\"/>\n",
" </defs>\n",
" <use xlink:href=\"#DejaVuSans-71\"/>\n",
" <use x=\"77.490234\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"116.353516\" xlink:href=\"#DejaVuSans-111\"/>\n",
" <use x=\"177.535156\" xlink:href=\"#DejaVuSans-117\"/>\n",
" <use x=\"240.914062\" xlink:href=\"#DejaVuSans-110\"/>\n",
" <use x=\"304.292969\" xlink:href=\"#DejaVuSans-100\"/>\n",
" <use x=\"367.769531\" xlink:href=\"#DejaVuSans-45\"/>\n",
" <use x=\"403.853516\" xlink:href=\"#DejaVuSans-115\"/>\n",
" <use x=\"455.953125\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"495.162109\" xlink:href=\"#DejaVuSans-97\"/>\n",
" <use x=\"556.441406\" xlink:href=\"#DejaVuSans-116\"/>\n",
" <use x=\"595.650391\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"657.173828\" xlink:href=\"#DejaVuSans-32\"/>\n",
" <use x=\"688.960938\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"750.484375\" xlink:href=\"#DejaVuSans-110\"/>\n",
" <use x=\"813.863281\" xlink:href=\"#DejaVuSans-101\"/>\n",
" <use x=\"875.386719\" xlink:href=\"#DejaVuSans-114\"/>\n",
" <use x=\"914.75\" xlink:href=\"#DejaVuSans-103\"/>\n",
" <use x=\"978.226562\" xlink:href=\"#DejaVuSans-121\"/>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <defs>\n",
" <clipPath id=\"pd4f85b6dad\">\n",
" <rect height=\"217.44\" width=\"334.8\" x=\"52.160938\" y=\"7.2\"/>\n",
" </clipPath>\n",
" </defs>\n",
"</svg>\n"
],
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -1834,21 +576,22 @@ ...@@ -1834,21 +576,22 @@
"\n", "\n",
"## References\n", "## References\n",
"\n", "\n",
"[1] [Cao, Yudong, et al. Quantum Chemistry in the Age of Quantum Computing. Chemical reviews 119.19 (2019): 10856-10915.](https://pubs.acs.org/doi/10.1021/acs.chemrev.8b00803)\n",
"\n", "\n",
"[2] [McArdle, Sam, et al. Quantum computational chemistry. Reviews of Modern Physics 92.1 (2020): 015003.](https://journals.aps.org/rmp/abstract/10.1103/RevModPhys.92.015003)\n", "[1] Cao, Yudong, et al. Quantum Chemistry in the Age of Quantum Computing. [Chemical reviews 119.19 (2019): 10856-10915.](https://pubs.acs.org/doi/10.1021/acs.chemrev.8b00803)\n",
"\n", "\n",
"[2] McArdle, Sam, et al. Quantum computational chemistry. [Reviews of Modern Physics 92.1 (2020): 015003.](https://journals.aps.org/rmp/abstract/10.1103/RevModPhys.92.015003)\n",
"\n", "\n",
"[3] [Peruzzo, A. et al. A variational eigenvalue solver on a photonic quantum processor. Nat. Commun. 5, 4213 (2014).](https://www.nature.com/articles/ncomms5213)\n",
"\n", "\n",
"[4] [Moll, Nikolaj, et al. Quantum optimization using variational algorithms on near-term quantum devices. Quantum Science and Technology 3.3 (2018): 030503.](https://iopscience.iop.org/article/10.1088/2058-9565/aab822)\n", "[3] Peruzzo, A. et al. A variational eigenvalue solver on a photonic quantum processor. [Nat. Commun. 5, 4213 (2014).](https://www.nature.com/articles/ncomms5213)\n",
"\n",
"[4] Moll, Nikolaj, et al. Quantum optimization using variational algorithms on near-term quantum devices. [Quantum Science and Technology 3.3 (2018): 030503.](https://iopscience.iop.org/article/10.1088/2058-9565/aab822)\n",
"\n",
"\n", "\n",
"[5] Helgaker, Trygve, Poul Jorgensen, and Jeppe Olsen. Molecular electronic-structure theory. John Wiley & Sons, 2014.\n", "[5] Helgaker, Trygve, Poul Jorgensen, and Jeppe Olsen. Molecular electronic-structure theory. John Wiley & Sons, 2014.\n",
"\n", "\n",
"[6] [Dirac, Paul Adrien Maurice. Quantum mechanics of many-electron systems. Proceedings of the Royal Society of London. Series A, Containing Papers of a Mathematical and Physical Character 123.792 (1929): 714-733.](https://royalsocietypublishing.org/doi/10.1098/rspa.1929.0094)\n", "[6] Dirac, Paul Adrien Maurice. Quantum mechanics of many-electron systems. [Proceedings of the Royal Society of London. Series A, Containing Papers of a Mathematical and Physical Character 123.792 (1929): 714-733.](https://royalsocietypublishing.org/doi/10.1098/rspa.1929.0094)\n",
"\n", "\n",
"[7] Szabo, Attila, and Neil S. Ostlund. Modern quantum chemistry: introduction to advanced electronic structure theory. Courier Corporation, 2012.\n", "[7] Szabo, Attila, and Neil S. Ostlund. Modern quantum chemistry: introduction to advanced electronic structure theory. Courier Corporation, 2012.\n"
"\n"
] ]
} }
], ],
...@@ -1868,7 +611,7 @@ ...@@ -1868,7 +611,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.9" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -20,19 +20,21 @@ ...@@ -20,19 +20,21 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:04.699669Z", "end_time": "2021-03-09T03:43:19.668798Z",
"start_time": "2021-01-09T10:38:59.947656Z" "start_time": "2021-03-09T03:43:16.454757Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy\n", "import numpy\n",
"from numpy import diag\n", "from numpy import diag\n",
"from numpy import pi as PI\n",
"import scipy\n", "import scipy\n",
"from paddle import fluid\n", "import scipy.stats\n",
"import paddle\n",
"from paddle import matmul, trace\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import dagger\n", "from paddle_quantum.utils import dagger"
"from paddle.complex import matmul, trace, transpose"
] ]
}, },
{ {
...@@ -50,8 +52,8 @@ ...@@ -50,8 +52,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:04.723926Z", "end_time": "2021-03-09T03:43:19.692450Z",
"start_time": "2021-01-09T10:39:04.702772Z" "start_time": "2021-03-09T03:43:19.672516Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -59,8 +61,8 @@ ...@@ -59,8 +61,8 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"[[ 0.2569-0.j -0.012 +0.0435j -0.0492-0.0055j -0.0548+0.0682j]\n", "[[ 0.2569+0.j -0.012 +0.0435j -0.0492-0.0055j -0.0548+0.0682j]\n",
" [-0.012 -0.0435j 0.2959+0.j 0.1061-0.0713j -0.0392-0.0971j]\n", " [-0.012 -0.0435j 0.2959-0.j 0.1061-0.0713j -0.0392-0.0971j]\n",
" [-0.0492+0.0055j 0.1061+0.0713j 0.2145-0.j 0.0294-0.1132j]\n", " [-0.0492+0.0055j 0.1061+0.0713j 0.2145-0.j 0.0294-0.1132j]\n",
" [-0.0548-0.0682j -0.0392+0.0971j 0.0294+0.1132j 0.2327+0.j ]]\n" " [-0.0548-0.0682j -0.0392+0.0971j 0.0294+0.1132j 0.2327+0.j ]]\n"
] ]
...@@ -92,8 +94,8 @@ ...@@ -92,8 +94,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:04.741146Z", "end_time": "2021-03-09T03:43:23.035187Z",
"start_time": "2021-01-09T10:39:04.729478Z" "start_time": "2021-03-09T03:43:23.015744Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -130,8 +132,8 @@ ...@@ -130,8 +132,8 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:04.763989Z", "end_time": "2021-03-09T03:43:25.122460Z",
"start_time": "2021-01-09T10:39:04.749814Z" "start_time": "2021-03-09T03:43:25.109448Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -139,23 +141,24 @@ ...@@ -139,23 +141,24 @@
"# 输入用来标记的量子态sigma\n", "# 输入用来标记的量子态sigma\n",
"sigma = diag([0.1, 0.2, 0.3, 0.4]).astype('complex128') \n", "sigma = diag([0.1, 0.2, 0.3, 0.4]).astype('complex128') \n",
"\n", "\n",
"class Net(fluid.dygraph.Layer):\n", "class Net(paddle.nn.Layer):\n",
" \"\"\"\n", " \"\"\"\n",
" Construct the model net\n", " Construct the model net\n",
" \"\"\"\n", " \"\"\"\n",
"\n", "\n",
" def __init__(self, shape, rho, sigma, param_attr =fluid.initializer.Uniform(low=0.0, high=2 * numpy.pi, seed=SEED), dtype='float64'):\n", " def __init__(self, shape, rho, sigma, dtype='float64'):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
" \n", " \n",
" \n", " \n",
" \n", " \n",
" # 将 numpy.ndarray 转换成 Paddle 动态图模式中支持的 variable\n", " # 将 numpy.ndarray 转换成 Paddle 中支持的 Tensor\n",
" self.rho = fluid.dygraph.to_variable(rho)\n", " self.rho = paddle.to_tensor(rho)\n",
" self.sigma = fluid.dygraph.to_variable(sigma)\n", " self.sigma = paddle.to_tensor(sigma)\n",
" \n", " \n",
" # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n", " # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n",
" self.theta = self.create_parameter(\n", " self.theta = self.create_parameter(shape=shape, \n",
" shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
"\n", "\n",
" # 定义损失函数和前向传播机制\n", " # 定义损失函数和前向传播机制\n",
" def forward(self, N):\n", " def forward(self, N):\n",
...@@ -169,7 +172,7 @@ ...@@ -169,7 +172,7 @@
" # 计算损失函数\n", " # 计算损失函数\n",
" loss = trace(matmul(self.sigma, rho_tilde))\n", " loss = trace(matmul(self.sigma, rho_tilde))\n",
"\n", "\n",
" return loss.real, rho_tilde" " return paddle.real(loss), rho_tilde"
] ]
}, },
{ {
...@@ -186,8 +189,8 @@ ...@@ -186,8 +189,8 @@
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:04.782143Z", "end_time": "2021-03-09T03:43:26.181791Z",
"start_time": "2021-01-09T10:39:04.771644Z" "start_time": "2021-03-09T03:43:26.175799Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -202,7 +205,7 @@ ...@@ -202,7 +205,7 @@
"source": [ "source": [
"## 进行训练\n", "## 进行训练\n",
"\n", "\n",
"- 当训练模型的各项参数都设置完成后,我们将数据转化为 Paddle 动态图中的变量,进而进行量子神经网络的训练。\n", "- 当训练模型的各项参数都设置完成后,我们将数据转化为 Paddle 中的张量,进而进行量子神经网络的训练。\n",
"- 过程中我们用的是 Adam Optimizer,也可以调用 Paddle 中提供的其他优化器。\n", "- 过程中我们用的是 Adam Optimizer,也可以调用 Paddle 中提供的其他优化器。\n",
"- 我们将训练过程中的结果依次输出。" "- 我们将训练过程中的结果依次输出。"
] ]
...@@ -212,8 +215,8 @@ ...@@ -212,8 +215,8 @@
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:06.249584Z", "end_time": "2021-03-09T03:43:32.881935Z",
"start_time": "2021-01-09T10:39:04.786391Z" "start_time": "2021-03-09T03:43:31.477330Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -221,40 +224,39 @@ ...@@ -221,40 +224,39 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 0 loss: 0.2354\n", "iter: 0 loss: 0.2494\n",
"iter: 10 loss: 0.1883\n", "iter: 10 loss: 0.1958\n",
"iter: 20 loss: 0.1817\n", "iter: 20 loss: 0.1843\n",
"iter: 30 loss: 0.1814\n", "iter: 30 loss: 0.1816\n",
"iter: 40 loss: 0.1809\n" "iter: 40 loss: 0.1805\n"
] ]
} }
], ],
"source": [ "source": [
"# 初始化paddle动态图机制\n", "paddle.seed(SEED)\n",
"with fluid.dygraph.guard():\n",
" \n",
" # 确定网络的参数维度\n",
" net = Net(shape=[THETA_SIZE], rho=rho, sigma=sigma)\n",
"\n", "\n",
" # 一般来说,我们利用 Adam 优化器来获得相对好的收敛\n", "# 确定网络的参数维度\n",
" # 当然你可以改成 SGD 或者是 RMS prop.\n", "net = Net(shape=[THETA_SIZE], rho=rho, sigma=sigma)\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "\n",
" \n", "# 一般来说,我们利用 Adam 优化器来获得相对好的收敛\n",
" # 优化循环\n", "# 当然你可以改成 SGD 或者是 RMS prop.\n",
" for itr in range(ITR):\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" \n", "\n",
" # 前向传播计算损失函数并返回估计的能谱\n", "# 优化循环\n",
" loss, rho_tilde = net(N)\n", "for itr in range(ITR):\n",
" rho_tilde_np = rho_tilde.numpy()\n", "\n",
" \n", " # 前向传播计算损失函数并返回估计的能谱\n",
" # 在动态图机制下,反向传播极小化损失函数\n", " loss, rho_tilde = net(N)\n",
" loss.backward()\n", " rho_tilde_np = rho_tilde.numpy()\n",
" opt.minimize(loss)\n", "\n",
" net.clear_gradients()\n", " # 反向传播极小化损失函数\n",
" \n", " loss.backward()\n",
" # 打印训练结果\n", " opt.minimize(loss)\n",
" if itr % 10 == 0:\n", " opt.clear_grad()\n",
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])" "\n",
" # 打印训练结果\n",
" if itr % 10 == 0:\n",
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])"
] ]
}, },
{ {
...@@ -271,8 +273,8 @@ ...@@ -271,8 +273,8 @@
"execution_count": 7, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:06.263643Z", "end_time": "2021-03-09T03:43:34.374882Z",
"start_time": "2021-01-09T10:39:06.254056Z" "start_time": "2021-03-09T03:43:34.365530Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -280,7 +282,7 @@ ...@@ -280,7 +282,7 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"The estimated spectrum is: [0.49951803 0.29739084 0.10256743 0.10052371]\n", "The estimated spectrum is: [0.49938069 0.29916354 0.10103808 0.10041768]\n",
"The target spectrum is: [0.5 0.3 0.1 0.1]\n" "The target spectrum is: [0.5 0.3 0.1 0.1]\n"
] ]
} }
...@@ -322,7 +324,7 @@ ...@@ -322,7 +324,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.0" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
...@@ -20,19 +20,21 @@ ...@@ -20,19 +20,21 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:18.985186Z", "end_time": "2021-03-09T03:43:45.281082Z",
"start_time": "2021-01-09T10:39:15.015255Z" "start_time": "2021-03-09T03:43:42.268516Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import numpy\n", "import numpy\n",
"from numpy import diag\n", "from numpy import diag\n",
"from numpy import pi as PI\n",
"import scipy\n", "import scipy\n",
"from paddle import fluid\n", "import scipy.stats\n",
"import paddle\n",
"from paddle import matmul, trace\n",
"from paddle_quantum.circuit import UAnsatz\n", "from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import dagger\n", "from paddle_quantum.utils import dagger"
"from paddle.complex import matmul, trace, transpose"
] ]
}, },
{ {
...@@ -56,8 +58,8 @@ ...@@ -56,8 +58,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:19.011525Z", "end_time": "2021-03-09T03:43:45.305154Z",
"start_time": "2021-01-09T10:39:18.987897Z" "start_time": "2021-03-09T03:43:45.283902Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -65,8 +67,8 @@ ...@@ -65,8 +67,8 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"[[ 0.2569-0.j -0.012 +0.0435j -0.0492-0.0055j -0.0548+0.0682j]\n", "[[ 0.2569+0.j -0.012 +0.0435j -0.0492-0.0055j -0.0548+0.0682j]\n",
" [-0.012 -0.0435j 0.2959+0.j 0.1061-0.0713j -0.0392-0.0971j]\n", " [-0.012 -0.0435j 0.2959-0.j 0.1061-0.0713j -0.0392-0.0971j]\n",
" [-0.0492+0.0055j 0.1061+0.0713j 0.2145-0.j 0.0294-0.1132j]\n", " [-0.0492+0.0055j 0.1061+0.0713j 0.2145-0.j 0.0294-0.1132j]\n",
" [-0.0548-0.0682j -0.0392+0.0971j 0.0294+0.1132j 0.2327+0.j ]]\n" " [-0.0548-0.0682j -0.0392+0.0971j 0.0294+0.1132j 0.2327+0.j ]]\n"
] ]
...@@ -98,8 +100,8 @@ ...@@ -98,8 +100,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:19.025782Z", "end_time": "2021-03-09T03:43:45.326631Z",
"start_time": "2021-01-09T10:39:19.017838Z" "start_time": "2021-03-09T03:43:45.319403Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -145,8 +147,8 @@ ...@@ -145,8 +147,8 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:19.048447Z", "end_time": "2021-03-09T03:43:45.348068Z",
"start_time": "2021-01-09T10:39:19.029044Z" "start_time": "2021-03-09T03:43:45.329388Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -154,23 +156,24 @@ ...@@ -154,23 +156,24 @@
"# Enter the quantum state sigma \n", "# Enter the quantum state sigma \n",
"sigma = diag([0.1, 0.2, 0.3, 0.4]).astype('complex128')\n", "sigma = diag([0.1, 0.2, 0.3, 0.4]).astype('complex128')\n",
"\n", "\n",
"class Net(fluid.dygraph.Layer):\n", "class Net(paddle.nn.Layer):\n",
" \"\"\"\n", " \"\"\"\n",
" Construct the model net\n", " Construct the model net\n",
" \"\"\"\n", " \"\"\"\n",
"\n", "\n",
" def __init__(self, shape, rho, sigma, param_attr =fluid.initializer.Uniform(low=0.0, high=2 * numpy.pi, seed=SEED), dtype='float64'):\n", " def __init__(self, shape, rho, sigma, dtype='float64'):\n",
" super(Net, self).__init__()\n", " super(Net, self).__init__()\n",
" \n", " \n",
" \n", " \n",
" \n", " \n",
" # Convert Numpy array to variable supported in Paddle dynamic graph mode\n", " # Convert Numpy array to Tensor supported in Paddle \n",
" self.rho = fluid.dygraph.to_variable(rho)\n", " self.rho = paddle.to_tensor(rho)\n",
" self.sigma = fluid.dygraph.to_variable(sigma)\n", " self.sigma = paddle.to_tensor(sigma)\n",
" \n", " \n",
" # Initialize the theta parameter list and fill the initial value with the uniform distribution of [0, 2*pi]\n", " # Initialize the theta parameter list and fill the initial value with the uniform distribution of [0, 2*pi]\n",
" self.theta = self.create_parameter(\n", " self.theta = self.create_parameter(shape=shape, \n",
" shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
"\n", "\n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self, N):\n", " def forward(self, N):\n",
...@@ -184,7 +187,7 @@ ...@@ -184,7 +187,7 @@
" # Calculate the loss function\n", " # Calculate the loss function\n",
" loss = trace(matmul(self.sigma, rho_tilde))\n", " loss = trace(matmul(self.sigma, rho_tilde))\n",
"\n", "\n",
" return loss.real, rho_tilde" " return paddle.real(loss), rho_tilde"
] ]
}, },
{ {
...@@ -201,8 +204,8 @@ ...@@ -201,8 +204,8 @@
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:19.110711Z", "end_time": "2021-03-09T03:43:46.380433Z",
"start_time": "2021-01-09T10:39:19.061263Z" "start_time": "2021-03-09T03:43:46.376425Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -217,7 +220,7 @@ ...@@ -217,7 +220,7 @@
"source": [ "source": [
"## Training process\n", "## Training process\n",
"\n", "\n",
"- After setting all the parameters of SSVQE model, we need to convert all the data into variables in the PaddlePaddle dynamic graph, and then train the quantum neural network.\n", "- After setting all the parameters of SSVQE model, we need to convert all the data into Tensor in the PaddlePaddle, and then train the quantum neural network.\n",
"- We used Adam Optimizer in training, and one can also call other optimizers provided in Paddle." "- We used Adam Optimizer in training, and one can also call other optimizers provided in Paddle."
] ]
}, },
...@@ -226,8 +229,8 @@ ...@@ -226,8 +229,8 @@
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:20.745068Z", "end_time": "2021-03-09T03:43:52.935466Z",
"start_time": "2021-01-09T10:39:19.142878Z" "start_time": "2021-03-09T03:43:51.655041Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -235,40 +238,39 @@ ...@@ -235,40 +238,39 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"iter: 0 loss: 0.2354\n", "iter: 0 loss: 0.2494\n",
"iter: 10 loss: 0.1883\n", "iter: 10 loss: 0.1958\n",
"iter: 20 loss: 0.1817\n", "iter: 20 loss: 0.1843\n",
"iter: 30 loss: 0.1814\n", "iter: 30 loss: 0.1816\n",
"iter: 40 loss: 0.1809\n" "iter: 40 loss: 0.1805\n"
] ]
} }
], ],
"source": [ "source": [
"# Initialize paddle dynamic graph mechanism\n", "paddle.seed(SEED)\n",
"with fluid.dygraph.guard():\n", "\n",
" \n", "# Determine the parameter dimension of the network\n",
" # Determine the parameter dimension of the network\n", "net = Net(shape=[THETA_SIZE], rho=rho, sigma=sigma)\n",
" net = Net(shape=[THETA_SIZE], rho=rho, sigma=sigma)\n", "\n",
"\n", "# We use Adam optimizer for better performance\n",
" # We use Adam optimizer for better performance\n", "# One can change it to SGD or RMSprop.\n",
" # One can change it to SGD or RMSprop.\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "\n",
" \n", "# Optimization loop\n",
" # Optimization loop\n", "for itr in range(ITR):\n",
" for itr in range(ITR):\n", "\n",
" \n", " # Forward propagation calculates the loss function and returns the estimated energy spectrum\n",
" # Forward propagation calculates the loss function and returns the estimated energy spectrum\n", " loss, rho_tilde = net(N)\n",
" loss, rho_tilde = net(N)\n", " rho_tilde_np = rho_tilde.numpy()\n",
" rho_tilde_np = rho_tilde.numpy()\n", "\n",
" \n", " # Back propagation minimizes the loss function\n",
" # Under the dynamic graph mechanism, back propagation minimizes the loss function\n", " loss.backward()\n",
" loss.backward()\n", " opt.minimize(loss)\n",
" opt.minimize(loss)\n", " opt.clear_grad()\n",
" net.clear_gradients()\n", "\n",
" \n", " # Print training results\n",
" # Print training results\n", " if itr% 10 == 0:\n",
" if itr% 10 == 0:\n", " print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])"
" print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])"
] ]
}, },
{ {
...@@ -285,8 +287,8 @@ ...@@ -285,8 +287,8 @@
"execution_count": 7, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:39:20.757262Z", "end_time": "2021-03-09T03:43:54.017576Z",
"start_time": "2021-01-09T10:39:20.747722Z" "start_time": "2021-03-09T03:43:54.008564Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -294,7 +296,7 @@ ...@@ -294,7 +296,7 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"The estimated spectrum is: [0.49951803 0.29739084 0.10256743 0.10052371]\n", "The estimated spectrum is: [0.49938069 0.29916354 0.10103808 0.10041768]\n",
"The target spectrum is: [0.5 0.3 0.1 0.1]\n" "The target spectrum is: [0.5 0.3 0.1 0.1]\n"
] ]
} }
...@@ -337,7 +339,7 @@ ...@@ -337,7 +339,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.0" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -79,21 +79,21 @@ ...@@ -79,21 +79,21 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:49:00.623425Z", "end_time": "2021-03-09T03:44:34.008567Z",
"start_time": "2021-01-09T09:48:57.424722Z" "start_time": "2021-03-09T03:44:29.796997Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import time\n", "import time\n",
"import numpy as np\n", "import numpy as np\n",
"from numpy import pi as PI\n",
"from matplotlib import pyplot as plt\n", "from matplotlib import pyplot as plt\n",
"%config InlineBackend.figure_format = 'svg'\n",
"from scipy.stats import unitary_group\n", "from scipy.stats import unitary_group\n",
"from scipy.linalg import norm\n", "from scipy.linalg import norm\n",
"\n", "\n",
"import paddle.fluid as fluid\n", "import paddle\n",
"from paddle.complex import matmul, transpose, trace\n", "from paddle import matmul, transpose, trace\n",
"from paddle_quantum.circuit import *\n", "from paddle_quantum.circuit import *\n",
"from paddle_quantum.utils import *\n", "from paddle_quantum.utils import *\n",
"\n", "\n",
...@@ -125,8 +125,8 @@ ...@@ -125,8 +125,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:49:00.646056Z", "end_time": "2021-03-09T03:44:34.056721Z",
"start_time": "2021-01-09T09:49:00.626439Z" "start_time": "2021-03-09T03:44:34.012222Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -161,8 +161,8 @@ ...@@ -161,8 +161,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:49:00.667463Z", "end_time": "2021-03-09T03:44:34.093725Z",
"start_time": "2021-01-09T09:49:00.650150Z" "start_time": "2021-03-09T03:44:34.063353Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -204,8 +204,8 @@ ...@@ -204,8 +204,8 @@
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:49:00.680019Z", "end_time": "2021-03-09T03:44:34.112670Z",
"start_time": "2021-01-09T09:49:00.671042Z" "start_time": "2021-03-09T03:44:34.098847Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -272,8 +272,8 @@ ...@@ -272,8 +272,8 @@
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:49:00.724542Z", "end_time": "2021-03-09T03:44:34.132465Z",
"start_time": "2021-01-09T09:49:00.704404Z" "start_time": "2021-03-09T03:44:34.116446Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -334,8 +334,8 @@ ...@@ -334,8 +334,8 @@
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:49:01.389789Z", "end_time": "2021-03-09T03:44:34.147570Z",
"start_time": "2021-01-09T09:49:01.383262Z" "start_time": "2021-03-09T03:44:34.138265Z"
} }
}, },
"outputs": [ "outputs": [
...@@ -376,14 +376,14 @@ ...@@ -376,14 +376,14 @@
"execution_count": 7, "execution_count": 7,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:49:02.113260Z", "end_time": "2021-03-09T03:44:34.245692Z",
"start_time": "2021-01-09T09:49:02.104652Z" "start_time": "2021-03-09T03:44:34.226859Z"
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"# Set circuit parameters\n", "# Set circuit parameters\n",
"cir_depth = 40 # circuit depth\n", "cir_depth = 20 # circuit depth\n",
"block_len = 2 # length of each block\n", "block_len = 2 # length of each block\n",
"theta_size = N * block_len * cir_depth # size of the network parameter theta\n", "theta_size = N * block_len * cir_depth # size of the network parameter theta\n",
"\n", "\n",
...@@ -420,17 +420,33 @@ ...@@ -420,17 +420,33 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 9,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:51:53.804588Z", "end_time": "2021-03-09T03:46:12.944634Z",
"start_time": "2021-01-09T09:49:02.916138Z" "start_time": "2021-03-09T03:44:50.626213Z"
} }
}, },
"outputs": [ "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"iter: 0 loss: -235.9752\n",
"iter: 10 loss: -1635.7805\n",
"iter: 20 loss: -1967.8480\n",
"iter: 30 loss: -2154.2274\n",
"iter: 40 loss: -2257.8776\n",
"iter: 50 loss: -2311.8162\n",
"iter: 60 loss: -2342.3099\n",
"iter: 70 loss: -2358.9515\n",
"iter: 80 loss: -2369.3172\n",
"iter: 90 loss: -2375.9682\n"
]
},
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -442,22 +458,25 @@ ...@@ -442,22 +458,25 @@
} }
], ],
"source": [ "source": [
"class NET(fluid.dygraph.Layer):\n", "class NET(paddle.nn.Layer):\n",
" \n", " \n",
" # Initialize the list of learnable parameters, and fill the initial value with the uniform distribution of [0, 2*pi]\n", " # Initialize the list of learnable parameters, and fill the initial value with the uniform distribution of [0, 2*pi]\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " def __init__(self, shape, dtype='float64'):\n",
" low=0.0, high=2 * np.pi), dtype='float64'):\n",
" super(NET, self).__init__()\n", " super(NET, self).__init__()\n",
" \n", " \n",
" # Create the parameter theta for learning U\n", " # Create the parameter theta for learning U\n",
" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype,is_bias=False)\n", " self.theta = self.create_parameter(shape=shape,\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # Create a parameter phi to learn V_dagger\n", " # Create a parameter phi to learn V_dagger\n",
" self.phi = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.phi = self.create_parameter(shape=shape, \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # Convert Numpy array to variable supported in Paddle dynamic graph mode\n", " # Convert Numpy array to Tensor supported in Paddle\n",
" self.M = fluid.dygraph.to_variable(M)\n", " self.M = paddle.to_tensor(M)\n",
" self.weight = fluid.dygraph.to_variable(weight)\n", " self.weight = paddle.to_tensor(weight)\n",
"\n", "\n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -476,8 +495,8 @@ ...@@ -476,8 +495,8 @@
" \n", " \n",
" # Define loss function\n", " # Define loss function\n",
" for i in range(T):\n", " for i in range(T):\n",
" loss -= self.weight.real[i] * matmul(U_dagger,matmul(self.M, V)).real[i][i]\n", " loss -= paddle.real(self.weight)[i] * paddle.real(matmul(U_dagger,matmul(self.M, V)))[i][i]\n",
" singular_values[i] = (matmul(U_dagger, matmul(self.M, V)).real[i][i]).numpy()\n", " singular_values[i] = paddle.real(matmul(U_dagger, matmul(self.M, V)))[i][i].numpy()\n",
" \n", " \n",
" # Function returns two matrices U and V_dagger, learned singular values and loss function\n", " # Function returns two matrices U and V_dagger, learned singular values and loss function\n",
" return U, V_dagger, loss, singular_values\n", " return U, V_dagger, loss, singular_values\n",
...@@ -486,37 +505,38 @@ ...@@ -486,37 +505,38 @@
"loss_list, singular_value_list = [], []\n", "loss_list, singular_value_list = [], []\n",
"U_learned, V_dagger_learned = [], []\n", "U_learned, V_dagger_learned = [], []\n",
"\n", "\n",
"# Start Paddle dynamic graph mode\n",
"with fluid.dygraph.guard():\n",
" \n", " \n",
" # Determine the parameter dimension of the network\n", "# Determine the parameter dimension of the network\n",
" net = NET([theta_size])\n", "net = NET([theta_size])\n",
" \n", "\n",
" # We use Adam optimizer for better performance\n", "# We use Adam optimizer for better performance\n",
" # One can change it to SGD or RMSprop.\n", "# One can change it to SGD or RMSprop.\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
" \n", "\n",
" # Optimization cycle\n", "# Optimization cycle\n",
" for itr in range(ITR):\n", "for itr in range(ITR):\n",
" \n",
" # Forward propagation to calculate loss function\n",
" U, V_dagger, loss, singular_values = net()\n",
" \n",
" # Under the dynamic graph mode, back propagation minimizes the loss function\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" net.clear_gradients()\n",
"\n", "\n",
" # Record optimization intermediate results\n", " # Forward propagation to calculate loss function\n",
" loss_list.append(loss[0][0].numpy())\n", " U, V_dagger, loss, singular_values = net()\n",
" singular_value_list.append(singular_values)\n",
"\n", "\n",
" # Record the last two learned unitary matrices\n", " # Back propagation minimizes the loss function\n",
" U_learned = U.real.numpy() + 1j * U.imag.numpy()\n", " loss.backward()\n",
" V_dagger_learned = V_dagger.real.numpy() + 1j * V_dagger.imag.numpy()\n", " opt.minimize(loss)\n",
" opt.clear_grad()\n",
"\n",
" # Record optimization intermediate results\n",
" loss_list.append(loss[0][0].numpy())\n",
" singular_value_list.append(singular_values)\n",
" \n",
" if itr% 10 == 0:\n",
" print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])\n",
"\n", "\n",
"# Draw a learning curve\n", "# Draw a learning curve\n",
"loss_plot(loss_list)" "loss_plot(loss_list)\n",
"\n",
"# Record the last two learned unitary matrices\n",
"U_learned = U.numpy()\n",
"V_dagger_learned = V_dagger.numpy()"
] ]
}, },
{ {
...@@ -548,17 +568,17 @@ ...@@ -548,17 +568,17 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": 10,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:54:23.390172Z", "end_time": "2021-03-09T03:46:13.453107Z",
"start_time": "2021-01-09T09:54:21.827423Z" "start_time": "2021-03-09T03:46:12.949847Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEKCAYAAAAfGVI8AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/d3fzzAAAACXBIWXMAAAsTAAALEwEAmpwYAABEKElEQVR4nO3dd3hUddbA8e9JIYUWCCGE3gklkECkiEhTQUVUpMiqK+rq2tuLbd1V3CaKBbtrWUUsFBEULIg0CwsIhJ4gYoKUUEMngZTz/nFvQggpE0gyKefzPPNk5t47d85Mkjn310VVMcYYU3X5eDsAY4wx3mWJwBhjqjhLBMYYU8VZIjDGmCrOEoExxlRxft4O4GzUq1dPmzdv7u0wjDGmQlm5cuU+VQ3Lu71CJoLmzZuzYsUKb4dhjDEViohszW+7VQ0ZY0wVZ4nAGGOqOEsExhhTxVXINgJjyoM9e/YwduxYEhISyMrK8nY4xgDg4+NDZGQkzz33HPXr1/foOZYIjDlLY8eOpX///rz77rv4+/t7OxxjAEhPT2fy5MmMHTuWDz74wKPnVJmqoVlxOxj69Kcse6IHVzw9g1lxO7wdkqngEhISuP766y0JmHLF39+fG264gYSEBI+fUyVKBLPidvDYZ+v4i37Ceb6bGHHsYx77rDoAV8U08nJ0pqLKysqyJGDKJX9//2JVV1aJEsGEuZuokb6PEb6L8RFlhO/31Ejfz4S5m7wdmjHGeF2VSAQ7D6Zyr99MfMkEwIdM7vH7jJ0HU70cmTHnxtfXl+joaDp16sQVV1zBwYMHvRbLokWLWLJkSYmdb9asWWzcuDHn8RNPPMF3331XYufP64svvmD8+PEeHXv8+HFCQ0M5fPjwaduvuuoqpk6dCjjxd+7cmcjISDp16sSnn36ac9zSpUvp0aMH0dHRtG/fnnHjxpGUlETjxo3PuJKPjo5m2bJljBs3jkaNGhEdHU2bNm0YNmzYaZ/PuagSiSCqdiojfBfjL84HHCCZjPD9nk6107wcmalKZsXtoPf4BbR49Et6j19QIu1UQUFBrF69mvXr11O3bl1ee+21Eoj07BSWCDIyMop9vryJ4O9//zsXXXTRWcdXlKFDh/Loo496dGxwcDCDBg1i5syZOdsOHTrEjz/+yBVXXMGaNWsYO3Ysn3/+OQkJCcyePZtHHnmElStXAnDjjTfy1ltv5fzuRo4cSfPmzWnatCk//PBDzjkTEhI4cuQIPXr0AOCBBx5g9erVbN68mVGjRjFgwAD27t17zu+9SiSCiRHzEE5fic2HLF6K+NZLEZmqJrudasfBVBTYcTCVxz5bV6KdFnr16sWOHc75tmzZwuDBg+nWrRt9+vTJaTjcvXs3V199NV26dKFLly45X9wvvPACnTp1olOnTkycOBGApKQk2rdvz6233krHjh255JJLSE11StEvv/wyHTp0oHPnzlx77bUkJSXx5ptv8uKLLxIdHc0PP/zAmDFjuP322+nRowcPP/ww48aN47nnnsuJt1OnTiQlJQHwwQcf0LlzZ7p06cINN9zAkiVL+OKLL3jooYeIjo5my5YtjBkzJueqev78+cTExBAVFcXNN9/MiRMnAGf6mSeffJKuXbsSFRWVb4Npz5492bBhQ87jfv36sWLFCt5//33uvvtuAGbPnk2PHj2IiYnhoosuYvfu3WecZ/To0UyZMiXn8cyZMxk0aBDBwcE899xz/OUvf6FFixYAtGjRgr/85S88//zzgNP1OCIiAnBKdR06dMj3nFOmTOHaa6/N9/c9atQoLrnkEj7++ON89xdHlWgsbpm2AeT0K5IAyXC2G1NCRv3nfwXui/v9ICczTy/yp6ZnMm72Bq6KaUTKsZPc8eHK0/ZP/XMvj187MzOT+fPnc8sttwBw22238eabb9KmTRuWLVvGnXfeyYIFC7j33nvp27cvM2fOJDMzk6NHj7Jy5Uree+89li1bhqrSo0cP+vbtS506ddi8eTOffPIJb7/9NiNHjmTGjBlcf/31jB8/nsTERAICAjh48CAhISHcfvvt1KhRg7FjxwLw7rvvsn37dpYsWYKvry/jxo3LN/YNGzbwz3/+kyVLllCvXj1SUlKoW7cuQ4cOZciQIQwfPvy049PS0hgzZgzz58+nbdu2/PGPf+SNN97g/vvvB6BevXqsWrWK119/neeee4533nnntOePGjWKadOm8dRTT5GcnExycjKxsbGsX78+55gLLriApUuXIiK88847PPvsszlf4tkGDRrEn/70J/bv309oaChTpkzJSSQbNmzI+RyyxcbG8sorrwDOlX27du3o168fgwcP5sYbbyQwMJCRI0cSHR3NK6+8gp+fH1OnTmX69OkF/t67du1arN5BBakSJQJu/xHGHYJxhzh4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Gv82lazMTG+HYyqzxc/C70th8TMlfmqbhrpsp6FOTk7OmYYCnKkvAgICGD58OF9++SUnT57M+Rx37tyZ77QdLVu25IUXXuDll18u6tdbulS1wt26deumJW3FF2+oPllL134/q8TPbSqnM/4O/3vZmbdlbzn7ThxTfesi1XEhqk/Wcn6+fZHqqg+d/Uf3nflcD1SvXl1VVTMyMnT48OH69ddfq6rqgAED9JdfflFV1aVLl2r//v1VVXXkyJH64osv5jzn4MGDumLFCu3UqZMePXpUjxw5oh06dNBVq1ZpYmKi+vr6alxcnKqqjhgxQidPnqyqqhEREZqWlqaqqgcOHFBV1SeffFInTJiQE9uNN96ol19+uWZkZOS7v2PHjpqYmKjr16/XNm3a6N69e1VVdf/+/TnPnz59+mnnmz59uqampmrjxo1106ZNqqp6ww035LynZs2a6csvv6yqqq+99precsstZ3xmL7zwgj7xxBOqqrpz505t27atqqq+9957etddd6mqakpKimZlZamq6ttvv60PPvjgGeeJi4vTsLAw7dmzpz7++OM5n7eq6uWXX66zZjnfJU8//bT+3//9n6qqJiYmaseOHU87z4EDBzQwMPCM85+r/L4ngRWaz3eqlQhcnS6+gQPU5Niyyd4OxVRWh36H7NlVVOHg7+d8SpuG2nvTUEdHR/Pbb7/x0EMPkZKSwnnnnUd8fDxw+gIzuauF8qPlYL4zm4PZFRBYnY87vsKEOGHh4TTCawV6OyRT0dz0ZcH7ThyGtIOcGjivzuPWbp139dDCn18Am4a64JjLYhrq7MQ5bNgwfHx8+Oqrr2jfvj1XXnklDzzwAKtWreL48eN069atwHjj4uJo37792b3ZEmIlglz697+E41n+TP15m7dDMZXN4mdB8yxOo1kl1lZg01CX/TTUP/30EwcOHADg5MmTbNy4kWbNmgFOgujfvz8333xzoaWBpKQkxo4dyz333FOs+EuaJYJcmterzgON4jn/x5vISD+3laOMOc325ZB58vRtmSed7SXEpqH2XElMQ71lyxb69u2b8znExsZyzTXX5OwfPXo0a9asOSMRbNmyJaf76MiRI7n33nu56aabihV/SSuzaahLUklMQ12QuG/eI2bp/SRfPomI864qldcwlYNNQ23Ks/I6DXWFEDXgD2iNcCI2f+LtUIwxpkxY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\n", "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEKCAYAAAAfGVI8AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAABFZUlEQVR4nO3dd3hUZfbA8e9JDzWUEJpAQHqABJCiIEUEG6hIkVVWlLW31QXr/hTXVVER++pa1oIFbGAXkSoiIBCUFmoA6SWEloS08/vjnYQAKRNIMinn8zzzZObeO3fOhDBn3nLPK6qKMcaYisvP1wEYY4zxLUsExhhTwVkiMMaYCs4SgTHGVHCWCIwxpoIL8HUAp6N27drapEkTX4dhjDFlytKlS/epavjJ28tkImjSpAlLlizxdRjGGFOmiMiW3LZb15AxxlRwlgiMMaaCs0RgjDEVXJkcIzCmNNizZw9jxowhLi6OzMxMX4djDAB+fn60atWKCRMmUKdOHa+eY4nAmNM0ZswY+vTpw9tvv01gYKCvwzEGgLS0NCZNmsSYMWN4//33vXpOhekamha7nUFPfcaiR7oy8KnPmRa73dchmTIuLi6Oa6+91pKAKVUCAwMZOXIkcXFxXj+nQrQIpsVu58EvVvCQfsw5/msZevQjHvyiMgBXxDTwcXSmrMrMzLQkYEqlwMDAQnVXVogWwbPT11IlbR9D/efiJ8pQ/3lUSdvPs9PX+jo0Y4zxuQqRCHYkJnNXwFT8yQDAjwzuDPiCHYnJPo7MmDPj7+9PdHQ0UVFRDBw4kMTERJ/FMmfOHBYsWFBk55s2bRqrV6/OfvzII4/w008/Fdn5T/bVV18xfvx4r45NSkqiVq1aHDp06ITtV1xxBVOmTAFc/O3bt6dVq1ZERUXx2WefZR+3cOFCunbtSnR0NK1bt2bcuHFs3ryZhg0bnvJNPjo6mkWLFjFu3DgaNGhAdHQ0zZs3Z/DgwSf8fs5EhUgE7aonM9R/LoHifsHBksFQ/3lEVU/xcWSmIpkWu53zxs8i8oFvOW/8rCIZpwoNDWX58uWsXLmSmjVr8uqrrxZBpKcnv0SQnp5e6POdnAj+9a9/0a9fv9OOryCDBg3igQce8OrYSpUqMWDAAKZOnZq97eDBg8yfP5+BAwfy+++/M2bMGL788kvi4uL4+uuvuf/++1m6dCkA1113HW+88Ub2v92wYcNo0qQJjRo14ueff84+Z1xcHIcPH6Zr164A3HPPPSxfvpz169czfPhw+vbty969e8/4vVeIRPBCvRkIJ67E5kcmL9b70UcRmYoma5xqe2IyCmxPTObBL1YU6aSF7t27s327O9/GjRu56KKL6NSpEz179sweONy9ezdXXnklHTp0oEOHDtkf3BMnTiQqKoqoqCheeOEFADZv3kzr1q258cYbadu2Lf379yc52bWiX3rpJdq0aUP79u25+uqr2bx5M6+//jrPP/880dHR/Pzzz4waNYpbbrmFrl27ct999zFu3DgmTJiQHW9UVBSbN28G4P3336d9+/Z06NCBkSNHsmDBAr766ivGjh1LdHQ0GzduZNSoUdnfqmfOnElMTAzt2rXjhhtu4NixY4ArP/Poo4/SsWNH2rVrl+uAabdu3Vi1alX24969e7NkyRLeffdd7rjjDgC+/vprunbtSkxMDP369WP37t2nnGfEiBFMnjw5+/HUqVMZMGAAlSpVYsKECTz00ENERkYCEBkZyUMPPcRzzz0HuKnH9erVA1yrrk2bNrmec/LkyVx99dW5/nsPHz6c/v3789FHH+W6vzAqxGBx05RVICd+IwmWdLfdmCIy/L+/5rkvdmsiqRknNvmT0zIY9/UqrohpQMLRVG79YOkJ+6fc3N3r187IyGDmzJmMHj0agJtuuonXX3+d5s2bs2jRIm677TZmzZrFXXfdRa9evZg6dSoZGRkcOXKEpUuX8s4777Bo0SJUla5du9KrVy9q1KjB+vXr+fjjj3nzzTcZNmwYn3/+Oddeey3jx48nPj6e4OBgEhMTCQsL45ZbbqFKlSqMGTMGgLfffptt27axYMEC/P39GTduXK6xr1q1in//+98sWLCA2rVrk5CQQM2aNRk0aBCXXXYZQ4YMOeH4lJQURo0axcyZM2nRogV//etfee211/j73/8OQO3atVm2bBn/+c9/mDBhAm+99dYJzx8+fDiffPIJjz32GDt37mTnzp107tyZlStXZh/To0cPFi5ciIjw1ltv8cwzz2R/iGcZMGAAf/vb39i/fz+1atVi8uTJ2Ylk1apV2b+HLJ07d+bll18G3Df7li1b0rt3by666CKuu+46QkJCGDZsGNHR0bz88ssEBAQwZcoUPv300zz/3Tt27Fio2UF5qRAtAm6ZD+MOwriDJN6x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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -610,11 +630,11 @@ ...@@ -610,11 +630,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 13, "execution_count": 11,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:55:17.832481Z", "end_time": "2021-03-09T03:47:14.486390Z",
"start_time": "2021-01-09T09:55:17.822888Z" "start_time": "2021-03-09T03:47:14.466171Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -631,17 +651,17 @@ ...@@ -631,17 +651,17 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 14, "execution_count": 12,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:55:19.530630Z", "end_time": "2021-03-09T03:47:15.837676Z",
"start_time": "2021-01-09T09:55:18.663734Z" "start_time": "2021-03-09T03:47:14.960968Z"
} }
}, },
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -653,7 +673,7 @@ ...@@ -653,7 +673,7 @@
}, },
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -665,7 +685,7 @@ ...@@ -665,7 +685,7 @@
}, },
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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\n",
"text/plain": [ "text/plain": [
"<Figure size 432x288 with 1 Axes>" "<Figure size 432x288 with 1 Axes>"
] ]
...@@ -690,11 +710,11 @@ ...@@ -690,11 +710,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 15, "execution_count": 13,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:55:24.681157Z", "end_time": "2021-03-09T03:47:15.858695Z",
"start_time": "2021-01-09T09:55:24.669666Z" "start_time": "2021-03-09T03:47:15.847413Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -727,11 +747,11 @@ ...@@ -727,11 +747,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 16, "execution_count": 14,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T09:55:31.997970Z", "end_time": "2021-03-09T03:47:16.002083Z",
"start_time": "2021-01-09T09:55:31.988769Z" "start_time": "2021-03-09T03:47:15.993385Z"
} }
}, },
"outputs": [], "outputs": [],
...@@ -756,54 +776,34 @@ ...@@ -756,54 +776,34 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 18, "execution_count": 15,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2021-01-09T10:06:45.142151Z", "end_time": "2021-03-09T03:47:16.619406Z",
"start_time": "2021-01-09T09:59:56.016358Z" "start_time": "2021-03-09T03:47:16.600512Z"
} }
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x143718be0>"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [ "source": [
"class NET(fluid.dygraph.Layer):\n", "class NET(paddle.nn.Layer):\n",
" \n", " \n",
" # Initialize the list of learnable parameters, and fill the initial value with the uniform distribution of [0, 2*pi]\n", " # Initialize the list of learnable parameters, and fill the initial value with the uniform distribution of [0, 2*pi]\n",
" def __init__(self, shape, param_attr=fluid.initializer.Uniform(\n", " def __init__(self, shape, dtype='float64'):\n",
" low=0.0, high=2 * np.pi), dtype='float64'):\n",
" super(NET, self).__init__()\n", " super(NET, self).__init__()\n",
" \n", " \n",
" # Create the parameter theta for learning U\n", " # Create the parameter theta for learning U\n",
" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.theta = self.create_parameter(shape=shape, \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # Create a parameter phi to learn V_dagger\n", " # Create a parameter phi to learn V_dagger\n",
" self.phi = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)\n", " self.phi = self.create_parameter(shape=shape, \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),\n",
" dtype=dtype, is_bias=False)\n",
" \n", " \n",
" # Convert Numpy array to variable supported in Paddle dynamic graph mode\n", " # Convert Numpy array to Tensor supported in Paddle\n",
" self.M = fluid.dygraph.to_variable(Mat_generator())\n", " self.M = paddle.to_tensor(Mat_generator())\n",
" self.weight = fluid.dygraph.to_variable(weight)\n", " self.weight = paddle.to_tensor(weight)\n",
"\n", "\n",
" # Define loss function and forward propagation mechanism\n", " # Define loss function and forward propagation mechanism\n",
" def forward(self):\n", " def forward(self):\n",
...@@ -822,44 +822,104 @@ ...@@ -822,44 +822,104 @@
" \n", " \n",
" # Define loss function\n", " # Define loss function\n",
" for i in range(T):\n", " for i in range(T):\n",
" loss -= self.weight.real[i]* matmul(U_dagger, matmul(self.M, V)).real[i][i]\n", " loss -= paddle.real(self.weight)[i] * paddle.real(matmul(U_dagger,matmul(self.M, V)))[i][i]\n",
" singular_values[i] = (matmul(U_dagger, matmul(self.M, V)).real[i][i]).numpy()\n", " singular_values[i] = paddle.real(matmul(U_dagger, matmul(self.M, V)))[i][i].numpy()\n",
" \n", " \n",
" # Function returns two matrices U and V_dagger, learned singular values and loss function\n", " # Function returns two matrices U and V_dagger, learned singular values and loss function\n",
" return U, V_dagger, loss, singular_values\n", " return U, V_dagger, loss, singular_values"
"\n", ]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:07.440520Z",
"start_time": "2021-03-09T03:47:21.094099Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"iter: 0 loss: 1537.4504\n",
"iter: 10 loss: -90754.6659\n",
"iter: 20 loss: -118936.4569\n",
"iter: 30 loss: -135978.2444\n",
"iter: 40 loss: -142946.4453\n",
"iter: 50 loss: -147064.3601\n",
"iter: 60 loss: -149600.0237\n",
"iter: 70 loss: -151044.1873\n",
"iter: 80 loss: -152079.2783\n",
"iter: 90 loss: -152850.4454\n",
"iter: 100 loss: -153473.4505\n",
"iter: 110 loss: -154018.4474\n",
"iter: 120 loss: -154517.7508\n",
"iter: 130 loss: -154952.2068\n",
"iter: 140 loss: -155299.7216\n",
"iter: 150 loss: -155558.2483\n",
"iter: 160 loss: -155750.0483\n",
"iter: 170 loss: -155900.1620\n",
"iter: 180 loss: -156023.2654\n",
"iter: 190 loss: -156125.9570\n"
]
},
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x137940510>"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# Record the optimization process\n", "# Record the optimization process\n",
"loss_list, singular_value_list = [], []\n", "loss_list, singular_value_list = [], []\n",
"U_learned, V_dagger_learned = [], []\n", "U_learned, V_dagger_learned = [], []\n",
" \n",
"net = NET([theta_size])\n",
"\n", "\n",
"# We use Adam optimizer for better performance\n",
"# One can change it to SGD or RMSprop.\n",
"opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"\n", "\n",
"# Start Paddle dynamic graph mode\n", "# Optimization loop\n",
"with fluid.dygraph.guard():\n", "for itr in range(ITR):\n",
" \n", "\n",
" net = NET([theta_size])\n", " # Forward propagation to calculate loss function\n",
" \n", " U, V_dagger, loss, singular_values = net()\n",
" # We use Adam optimizer for better performance\n",
" # One can change it to SGD or RMSprop.\n",
" opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())\n",
" \n",
" # Optimization loop\n",
" for itr in range(ITR):\n",
" \n",
" # Forward propagation to calculate loss function\n",
" U, V_dagger, loss, singular_values = net()\n",
" \n",
" # Under the dynamic graph mode, back propagation minimizes the loss function\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" net.clear_gradients()\n",
"\n", "\n",
" # Record optimization intermediate results\n", " # Back propagation minimizes the loss function\n",
" loss_list.append(loss[0][0].numpy())\n", " loss.backward()\n",
" singular_value_list.append(singular_values)\n", " opt.minimize(loss)\n",
" opt.clear_grad()\n",
"\n",
" # Record optimization intermediate results\n",
" loss_list.append(loss[0][0].numpy())\n",
" singular_value_list.append(singular_values)\n",
" \n",
" if itr% 10 == 0:\n",
" print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])\n",
"\n", "\n",
" # Record the last two unitary matrices learned\n", "# Record the last two unitary matrices learned\n",
" U_learned = U.real.numpy() + 1j * U.imag.numpy()\n", "U_learned = U.numpy()\n",
" V_dagger_learned = V_dagger.real.numpy() + 1j*V_dagger.imag.numpy()\n", "V_dagger_learned = V_dagger.numpy()\n",
"\n", "\n",
"singular_value = singular_value_list[-1]\n", "singular_value = singular_value_list[-1]\n",
"mat = np.matrix(U_learned.real[:, :T]) * np.diag(singular_value[:T])* np.matrix(V_dagger_learned.real[:T, :])\n", "mat = np.matrix(U_learned.real[:, :T]) * np.diag(singular_value[:T])* np.matrix(V_dagger_learned.real[:T, :])\n",
...@@ -898,7 +958,7 @@ ...@@ -898,7 +958,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.10" "version": "3.7.10"
}, },
"toc": { "toc": {
"base_numbering": 1, "base_numbering": 1,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册