提交 fbcf1296 编写于 作者: Q Quleaf

update to v2.1.0

上级 af346570
......@@ -18,7 +18,7 @@ English | [简体中文](README_CN.md)
- [Copyright and License](#copyright-and-license)
- [References](#references)
[Paddle Quantum (量桨)](https://qml.baidu.com/) is a quantum machine learning (QML) toolkit developed based on Baidu PaddlePaddle. It provides a platform to construct and train quantum neural networks (QNNs) with easy-to-use QML development kits suporting combinatorial optimization, quantum chemistry and other cutting-edge quantum applications, making PaddlePaddle the first and only deep learning framework in China that supports quantum machine learning.
[Paddle Quantum (量桨)](https://qml.baidu.com/) is a quantum machine learning (QML) toolkit developed based on Baidu PaddlePaddle. It provides a platform to construct and train quantum neural networks (QNNs) with easy-to-use QML development kits supporting combinatorial optimization, quantum chemistry and other cutting-edge quantum applications, making PaddlePaddle the first and only deep learning framework in China that supports quantum machine learning.
<p align="center">
<a href="https://qml.baidu.com/">
......@@ -33,7 +33,7 @@ English | [简体中文](README_CN.md)
</a>
<!-- PyPI -->
<a href="https://pypi.org/project/paddle-quantum/">
<img src="https://img.shields.io/badge/pypi-v2.0.1-orange.svg?style=flat-square&logo=pypi"/>
<img src="https://img.shields.io/badge/pypi-v2.1.0-orange.svg?style=flat-square&logo=pypi"/>
</a>
<!-- Python -->
<a href="https://www.python.org/">
......@@ -55,7 +55,7 @@ Paddle Quantum aims at establishing a bridge between artificial intelligence (AI
## Features
- Easy-to-use
- Many online learning resources (17+ tutorials)
- Many online learning resources (23+ tutorials)
- High efficiency in building QNN with various QNN templates
- Automatic differentiation
- Versatile
......@@ -66,7 +66,6 @@ Paddle Quantum aims at establishing a bridge between artificial intelligence (AI
- Toolboxes for Chemistry & Optimization
- LOCCNet for distributed quantum information processing
- Self-developed QML algorithms
## Install
......@@ -110,7 +109,7 @@ cd paddle_quantum/QAOA/example
python main.py
```
> For the introduction of QAOA, please refer to our [QAOA tutorial](https://github.com/PaddlePaddle/Quantum/tree/master/tutorial/QAOA).
> For the introduction of QAOA, please refer to our [QAOA tutorial](https://github.com/PaddlePaddle/Quantum/tree/master/tutorial/combinatorial_optimization/QAOA_EN.ipynb).
## Introduction and developments
......@@ -126,27 +125,42 @@ python main.py
### Tutorials
We provide tutorials covering combinatorial optimization, quantum chemistry, quantum classification, quantum entanglement manipulation and other popular QML research topics. Each tutorial currently supports reading on our website and running Jupyter Notebooks locally. For interested developers, we recommend them to download Jupyter Notebooks and play around with it. Here is the tutorial list,
1. [Quantum Approximation Optimization Algorithm (QAOA)](./tutorial/QAOA)
2. [Variational Quantum Eigensolver (VQE)](./tutorial/VQE)
3. [Quantum Classifier](./tutorial/Q-Classifier)
4. [The Barren Plateaus Phenomenon on Quantum Neural Networks (Barren Plateaus)](./tutorial/Barren)
5. [Quantum Autoencoder](./tutorial/Q-Autoencoder)
6. [Quantum GAN](./tutorial/Q-GAN)
7. [Subspace Search-Quantum Variational Quantum Eigensolver (SSVQE)](./tutorial/SSVQE)
8. [Variational Quantum State Diagonalization (VQSD)](./tutorial/VQSD)
9. [Gibbs State Preparation](./tutorial/Gibbs)
10. [Variational Quantum Singular Value Decomposition (VQSVD)](./tutorial/VQSVD)
11. [Local Operations and Classical Communication in QNN (LOCCNet)](./tutorial/LOCC/LOCCNET_Tutorial_EN.ipynb)
12. [Entanglement Distillation -- the BBPSSW protocol](./tutorial/LOCC)
13. [Entanglement Distillation -- the DEJMPS protocol](./tutorial/LOCC)
14. [Entanglement Distillation -- Protocol design with LOCCNet](./tutorial/LOCC)
15. [Quantum Teleportation](./tutorial/LOCC)
16. [Quantum State Discrimination](./tutorial/LOCC)
17. [Noise Model and Quantum Channel](./tutorial/Noise)
With the latest LOCCNet module, Paddle Quantum can efficiently simulate distributed quantum information processing tasks. Interested readers can start with this [tutorial on LOCCNet](./tutorial/LOCC/LOCCNET_Tutorial_EN.ipynb). In addition, Paddle Quantum supports QNN training on GPU. For users who want to get into more details, please check out the tutorial [Use Paddle Quantum on GPU](./introduction/PaddleQuantum_GPU_EN.ipynb). Moreover, Paddle Quantum could design robust quantum algorithms under noise. For more information, please see [Noise tutorial](./tutorial/Noise/Noise_EN.ipynb).
We provide tutorials covering quantum simulation, machine learning, combinatorial optimization, local operations and classical communication (LOCC), and other popular QML research topics. Each tutorial currently supports reading on our website and running Jupyter Notebooks locally. For interested developers, we recommend them to download Jupyter Notebooks and play around with it. Here is the tutorial list,
- [Quantum Simulation](./tutorial/quantum_simulation)
1. [Variational Quantum Eigensolver (VQE)](./tutorial/quantum_simulation/VQE_EN.ipynb)
2. [Subspace Search-Quantum Variational Quantum Eigensolver (SSVQE)](./tutorial/quantum_simulation/SSVQE_EN.ipynb)
3. [Variational Quantum State Diagonalization (VQSD)](./tutorial/quantum_simulation/VQSD_EN.ipynb)
4. [Gibbs State Preparation](./tutorial/quantum_simulation/GibbsState_EN.ipynb)
- [Machine Learning](./tutorial/machine_learning)
1. [Encoding Classical Data into Quantum States](./tutorial/machine_learning/DataEncoding_EN.ipynb)
2. [Quantum Classifier](./tutorial/machine_learning/QClassifier_EN.ipynb)
3. [Variational Shadow Quantum Learning (VSQL)](./tutorial/machine_learning/VSQL_EN.ipynb)
4. [Quantum Kernel Methods](./tutorial/machine_learning/QKernel_EN.ipynb)
5. [Quantum Autoencoder](./tutorial/machine_learning/QAutoencoder_EN.ipynb)
6. [Quantum GAN](./tutorial/machine_learning/QGAN_EN.ipynb)
7. [Variational Quantum Singular Value Decomposition (VQSVD)](./tutorial/machine_learning/VQSVD_EN.ipynb)
- [Combinatorial Optimization](./tutorial/combinatorial_optimization)
1. [Quantum Approximation Optimization Algorithm (QAOA)](./tutorial/combinatorial_optimization/QAOA_EN.ipynb)
2. [Solving Max-Cut Problem with QAOA](./tutorial/combinatorial_optimization/MAXCUT_EN.ipynb)
3. [Large-scale QAOA via Divide-and-Conquer](./tutorial/combinatorial_optimization/DC-QAOA_EN.ipynb)
4. [Travelling Salesman Problem](./tutorial/combinatorial_optimization/TSP_EN.ipynb)
- [LOCC with QNN (LOCCNet)](./tutorial/locc)
1. [Local Operations and Classical Communication in QNN (LOCCNet)](./tutorial/locc/LOCCNET_Tutorial_EN.ipynb)
2. [Entanglement Distillation -- the BBPSSW protocol](./tutorial/locc/EntanglementDistillation_BBPSSW_EN.ipynb)
3. [Entanglement Distillation -- the DEJMPS protocol](./tutorial/locc/EntanglementDistillation_DEJMPS_EN.ipynb)
4. [Entanglement Distillation -- Protocol design with LOCCNet](./tutorial/locc/EntanglementDistillation_LOCCNET_EN.ipynb)
5. [Quantum Teleportation](./tutorial/locc/QuantumTeleportation_EN.ipynb)
6. [Quantum State Discrimination](./tutorial/locc/StateDiscrimination_EN.ipynb)
- [QNN Research](./tutorial/qnn_research)
1. [The Barren Plateaus Phenomenon on Quantum Neural Networks (Barren Plateaus)](./tutorial/qnn_research/BarrenPlateaus_EN.ipynb)
2. [Noise Model and Quantum Channel](./tutorial/qnn_research/Noise_EN.ipynb)
With the latest LOCCNet module, Paddle Quantum can efficiently simulate distributed quantum information processing tasks. Interested readers can start with this [tutorial on LOCCNet](./tutorial/locc/LOCCNET_Tutorial_EN.ipynb). In addition, Paddle Quantum supports QNN training on GPU. For users who want to get into more details, please check out the tutorial [Use Paddle Quantum on GPU](./introduction/PaddleQuantum_GPU_EN.ipynb). Moreover, Paddle Quantum could design robust quantum algorithms under noise. For more information, please see [Noise tutorial](./tutorial/qnn_research/Noise_EN.ipynb).
### API documentation
......@@ -169,17 +183,19 @@ We also highly encourage developers to use Paddle Quantum as a research tool to
So far, we have done several projects with the help of Paddle Quantum as a powerful QML development platform.
[1] Wang, Y., Li, G. & Wang, X. Variational quantum Gibbs state preparation with a truncated Taylor series. arXiv:2005.08797 (2020). [[pdf](https://arxiv.org/pdf/2005.08797.pdf)]
[1] Wang, Youle, Guangxi Li, and Xin Wang. "Variational quantum gibbs state preparation with a truncated taylor series." arXiv preprint arXiv:2005.08797 (2020). [[pdf](https://arxiv.org/pdf/2005.08797.pdf)]
[2] Wang, X., Song, Z. & Wang, Y. Variational Quantum Singular Value Decomposition. arXiv:2006.02336 (2020). [[pdf](https://arxiv.org/pdf/2006.02336.pdf)]
[2] Wang, Xin, Zhixin Song, and Youle Wang. "Variational Quantum Singular Value Decomposition." arXiv preprint arXiv:2006.02336 (2020). [[pdf](https://arxiv.org/pdf/2006.02336.pdf)]
[3] Li, G., Song, Z. & Wang, X. VSQL: Variational Shadow Quantum Learning for Classification. arXiv:2012.08288 (2020). [[pdf]](https://arxiv.org/pdf/2012.08288.pdf), to appear at **AAAI 2021** conference.
[3] Li, Guangxi, Zhixin Song, and Xin Wang. "VSQL: Variational Shadow Quantum Learning for Classification." arXiv preprint arXiv:2012.08288 (2020). [[pdf]](https://arxiv.org/pdf/2012.08288.pdf), to appear at **AAAI 2021** conference.
[4] Chen, R., Song, Z., Zhao, X. & Wang, X. Variational Quantum Algorithms for Trace Distance and Fidelity Estimation. arXiv:2012.05768 (2020). [[pdf]](https://arxiv.org/pdf/2012.05768.pdf)
[4] Chen, Ranyiliu, et al. "Variational Quantum Algorithms for Trace Distance and Fidelity Estimation." arXiv preprint arXiv:2012.05768 (2020). [[pdf]](https://arxiv.org/pdf/2012.05768.pdf)
[5] Wang, K., Song, Z., Zhao, X., Wang Z. & Wang, X. Detecting and quantifying entanglement on near-term quantum devices. arXiv:2012.14311 (2020). [[pdf]](https://arxiv.org/pdf/2012.14311.pdf)
[5] Wang, Kun, et al. "Detecting and quantifying entanglement on near-term quantum devices." arXiv preprint arXiv:2012.14311 (2020). [[pdf]](https://arxiv.org/pdf/2012.14311.pdf)
[6] Zhao, X., Zhao, B., Wang, Z., Song, Z., & Wang, X. LOCCNet: a machine learning framework for distributed quantum information processing. arXiv:2101.12190 (2021). [[pdf]](https://arxiv.org/pdf/2101.12190.pdf)
[6] Zhao, Xuanqiang, et al. "LOCCNet: a machine learning framework for distributed quantum information processing." arXiv preprint arXiv:2101.12190 (2021). [[pdf]](https://arxiv.org/pdf/2101.12190.pdf)
[7] Cao, Chenfeng, and Xin Wang. "Noise-Assisted Quantum Autoencoder." Physical Review Applied 15.5 (2021): 054012. [[pdf]](https://journals.aps.org/prapplied/abstract/10.1103/PhysRevApplied.15.054012)
## Frequently Asked Questions
......
......@@ -34,7 +34,7 @@
</a>
<!-- PyPI -->
<a href="https://pypi.org/project/paddle-quantum/">
<img src="https://img.shields.io/badge/pypi-v2.0.1-orange.svg?style=flat-square&logo=pypi"/>
<img src="https://img.shields.io/badge/pypi-v2.1.0-orange.svg?style=flat-square&logo=pypi"/>
</a>
<!-- Python -->
<a href="https://www.python.org/">
......@@ -55,7 +55,7 @@
## 特色
- 轻松上手
- 丰富的在线学习资源(17+ 教程案例)
- 丰富的在线学习资源(23+ 教程案例)
- 通过模板高效搭建量子神经网络
- 自动微分框架
- 功能丰富
......@@ -109,7 +109,7 @@ cd paddle_quantum/QAOA/example
python main.py
```
> 关于 QAOA 的介绍可以参考我们的 [QAOA 教程](./tutorial/QAOA)。
> 关于 QAOA 的介绍可以参考我们的 [QAOA 教程](./tutorial/combinatorial_optimization/QAOA_CN.ipynb)。
## 入门与开发
......@@ -131,27 +131,42 @@ python main.py
Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为量子机器学习领域的研发提供强有力的支撑,也提供了丰富的案例供开发者学习。
在这里,我们提供了涵盖量子优化、量子化学、量子机器学习、量子纠缠处理等多个领域的案例供大家学习。每个教程目前支持网页阅览和运行 Jupyter Notebook 两种方式。我们推荐用户下载 Notebook 后,本地运行进行实践。
- [量子近似优化算法 (QAOA)](./tutorial/QAOA)
- [变分量子特征求解器 (VQE)](./tutorial/VQE)
- [量子分类器 (Quantum Classifier)](./tutorial/Q-Classifier)
- [量子神经网络的贫瘠高原效应 (Barren Plateaus)](./tutorial/Barren)
- [量子变分自编码器 (Quantum Autoencoder)](./tutorial/Q-Autoencoder)
- [量子生成对抗网络 (Quantum GAN)](./tutorial/Q-GAN)
- [子空间搜索 - 量子变分特征求解器 (SSVQE)](./tutorial/SSVQE)
- [变分量子态对角化算法 (VQSD)](./tutorial/VQSD)
- [吉布斯态的制备 (Gibbs State Preparation)](./tutorial/Gibbs)
- [变分量子奇异值分解 (VQSVD)](./tutorial/VQSVD)
- [LOCC 量子神经网络](./tutorial/LOCC/LOCCNET_Tutorial_CN.ipynb)
- [纠缠蒸馏 -- BBPSSW 协议](./tutorial/LOCC)
- [纠缠蒸馏 -- DEJMPS 协议](./tutorial/LOCC)
- [纠缠蒸馏 -- LOCCNet 设计协议](./tutorial/LOCC)
- [量子隐态传输](./tutorial/LOCC)
- [量子态分辨](./tutorial/LOCC)
- [噪声模型与量子信道](./tutorial/Noise)
随着 LOCCNet 模组的推出,量桨现已支持分布式量子信息处理任务的高效模拟和开发。感兴趣的读者请参见[教程](./tutorial/LOCC/LOCCNET_Tutorial_CN.ipynb)。Paddle Quantum 也支持在 GPU 上进行量子机器学习的训练,具体的方法请参考案例:[在 GPU 上使用 Paddle Quantum](./introduction/PaddleQuantum_GPU_CN.ipynb)。此外,量桨可以基于噪声模块进行含噪算法的开发以及研究,详情请见[噪声模块教程](./tutorial/Noise/Noise_CN.ipynb)
在这里,我们提供了涵盖量子模拟、机器学习、组合优化、本地操作与经典通讯(local operations and classical communication, LOCC)、量子神经网络等多个领域的案例供大家学习。每个教程目前支持网页阅览和运行 Jupyter Notebook 两种方式。我们推荐用户下载 Notebook 后,本地运行进行实践。
- [量子模拟](./tutorial/quantum_simulation)
1. [变分量子特征求解器(VQE)](./tutorial/quantum_simulation/VQE_CN.ipynb)
2. [子空间搜索 - 量子变分特征求解器(SSVQE)](./tutorial/quantum_simulation/SSVQE_CN.ipynb)
3. [变分量子态对角化算法(VQSD)](./tutorial/quantum_simulation/VQSD_CN.ipynb)
4. [吉布斯态的制备(Gibbs State Preparation)](./tutorial/quantum_simulation/GibbsState_CN.ipynb)
- [机器学习](./tutorial/machine_learning)
1. [量子态编码经典数据](./tutorial/machine_learning/DataEncoding_CN.ipynb)
2. [量子分类器(Quantum Classifier)](./tutorial/machine_learning/QClassifier_CN.ipynb)
3. [变分影子量子学习(VSQL)](./tutorial/machine_learning/VSQL_CN.ipynb)
4. [量子核方法(Quantum Kernel)](./tutorial/machine_learning/QKernel_CN.ipynb)
5. [量子变分自编码器(Quantum Autoencoder)](./tutorial/machine_learning/QAutoencoder_CN.ipynb)
6. [量子生成对抗网络(Quantum GAN)](./tutorial/machine_learning/QGAN_CN.ipynb)
7. [变分量子奇异值分解(VQSVD)](./tutorial/machine_learning/VQSVD_CN.ipynb)
- [组合优化](./tutorial/combinatorial_optimization)
1. [量子近似优化算法(QAOA)](./tutorial/combinatorial_optimization/QAOA_CN.ipynb)
2. [QAOA 求解最大割问题](./tutorial/combinatorial_optimization/MAXCUT_CN.ipynb)
3. [大规模量子近似优化分治算法(DC-QAOA)](./tutorial/combinatorial_optimization/DC-QAOA_CN.ipynb)
4. [旅行商问题](./tutorial/combinatorial_optimization/TSP_CN.ipynb)
- [LOCC 量子神经网络(LOCCNet)](./tutorial/locc)
1. [LOCC 量子神经网络](./tutorial/locc/LOCCNET_Tutorial_CN.ipynb)
2. [纠缠蒸馏 -- BBPSSW 协议](./tutorial/locc/EntanglementDistillation_BBPSSW_CN.ipynb)
3. [纠缠蒸馏 -- DEJMPS 协议](./tutorial/locc/EntanglementDistillation_DEJMPS_CN.ipynb)
4. [纠缠蒸馏 -- LOCCNet 设计协议](./tutorial/locc/EntanglementDistillation_LOCCNET_CN.ipynb)
5. [量子隐态传输](./tutorial/locc/QuantumTeleportation_CN.ipynb)
6. [量子态分辨](./tutorial/locc/StateDiscrimination_CN.ipynb)
- [量子神经网络研究](./tutorial/qnn_research)
1. [量子神经网络的贫瘠高原效应(Barren Plateaus)](./tutorial/qnn_research/BarrenPlateaus_CN.ipynb)
2. [噪声模型与量子信道](./tutorial/qnn_research/Noise_CN.ipynb)
随着 LOCCNet 模组的推出,量桨现已支持分布式量子信息处理任务的高效模拟和开发。感兴趣的读者请参见[教程](./tutorial/locc/LOCCNET_Tutorial_CN.ipynb)。Paddle Quantum 也支持在 GPU 上进行量子机器学习的训练,具体的方法请参考案例:[在 GPU 上使用 Paddle Quantum](./introduction/PaddleQuantum_GPU_CN.ipynb)。此外,量桨可以基于噪声模块进行含噪算法的开发以及研究,详情请见[噪声模块教程](./tutorial/qnn_research/Noise_CN.ipynb)
### API 文档
......@@ -169,19 +184,28 @@ Paddle Quantum 使用 setuptools 的 develop 模式进行安装,相关代码
## 使用 Paddle Quantum 的工作
我们非常欢迎开发者使用 Paddle Quantum 进行量子机器学习的研发,如果您的工作有使用 Paddle Quantum,也非常欢迎联系我们。目前使用 Paddle Quantum 的代表性工作包括了吉布斯态的制备和变分量子奇异值分解
我们非常欢迎开发者使用 Paddle Quantum 进行量子机器学习的研发,如果您的工作有使用 Paddle Quantum,也非常欢迎联系我们。以下为 BibTeX 的引用方式
[1] Wang, Y., Li, G. & Wang, X. Variational quantum Gibbs state preparation with a truncated Taylor series. arXiv:2005.08797 (2020). [[pdf](https://arxiv.org/pdf/2005.08797.pdf)]
> @misc{Paddlequantum,
> title = {{Paddle Quantum}},
> year = {2020},
> url = {https://github.com/PaddlePaddle/Quantum}, }
[2] Wang, X., Song, Z. & Wang, Y. Variational Quantum Singular Value Decomposition. arXiv:2006.02336 (2020). [[pdf](https://arxiv.org/pdf/2006.02336.pdf)]
目前使用 Paddle Quantum 的代表性工作包括了吉布斯态的制备和变分量子奇异值分解:
[3] Li, G., Song, Z. & Wang, X. VSQL: Variational Shadow Quantum Learning for Classification. arXiv:2012.08288 (2020). [[pdf]](https://arxiv.org/pdf/2012.08288.pdf), to appear at **AAAI 2021** conference.
[1] Wang, Youle, Guangxi Li, and Xin Wang. "Variational quantum gibbs state preparation with a truncated taylor series." arXiv preprint arXiv:2005.08797 (2020). [[pdf](https://arxiv.org/pdf/2005.08797.pdf)]
[4] Chen, R., et al. Variational Quantum Algorithms for Trace Distance and Fidelity Estimation. arXiv:2012.05768 (2020). [[pdf]](https://arxiv.org/pdf/2012.05768.pdf)
[2] Wang, Xin, Zhixin Song, and Youle Wang. "Variational Quantum Singular Value Decomposition." arXiv preprint arXiv:2006.02336 (2020). [[pdf](https://arxiv.org/pdf/2006.02336.pdf)]
[5] Wang, K., et al. Detecting and quantifying entanglement on near-term quantum devices. arXiv:2012.14311 (2020). [[pdf]](https://arxiv.org/pdf/2012.14311.pdf)
[3] Li, Guangxi, Zhixin Song, and Xin Wang. "VSQL: Variational Shadow Quantum Learning for Classification." arXiv preprint arXiv:2012.08288 (2020). [[pdf]](https://arxiv.org/pdf/2012.08288.pdf), to appear at **AAAI 2021** conference.
[6] Zhao, X., Zhao, B., Wang, Z., Song, Z., & Wang, X. LOCCNet: a machine learning framework for distributed quantum information processing. arXiv:2101.12190 (2021). [[pdf]](https://arxiv.org/pdf/2101.12190.pdf)
[4] Chen, Ranyiliu, et al. "Variational Quantum Algorithms for Trace Distance and Fidelity Estimation." arXiv preprint arXiv:2012.05768 (2020). [[pdf]](https://arxiv.org/pdf/2012.05768.pdf)
[5] Wang, Kun, et al. "Detecting and quantifying entanglement on near-term quantum devices." arXiv preprint arXiv:2012.14311 (2020). [[pdf]](https://arxiv.org/pdf/2012.14311.pdf)
[6] Zhao, Xuanqiang, et al. "LOCCNet: a machine learning framework for distributed quantum information processing." arXiv preprint arXiv:2101.12190 (2021). [[pdf]](https://arxiv.org/pdf/2101.12190.pdf)
[7] Cao, Chenfeng, and Xin Wang. "Noise-Assisted Quantum Autoencoder." Physical Review Applied 15.5 (2021): 054012. [[pdf]](https://journals.aps.org/prapplied/abstract/10.1103/PhysRevApplied.15.054012)
## FAQ
......
......@@ -6,7 +6,6 @@
"source": [
"# 在 GPU 上使用量桨\n",
"\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
......@@ -138,7 +137,7 @@
"source": [
"我们可以在命令行中输入`nvidia-smi`来查看 GPU 的使用情况,包括有哪些程序在哪些 GPU 上运行,以及其显存占用情况。\n",
"\n",
"这里,我们以 [VQE](https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/VQE) 为例来说明我们该如何使用 GPU。首先,导入相关的包并定义相关的变量和函数。"
"这里,我们以 [VQE](../tutorial/quantum_simulation/VQE_CN.ipynb) 为例来说明我们该如何使用 GPU。首先,导入相关的包并定义相关的变量和函数。"
]
},
{
......@@ -160,7 +159,7 @@
"\n",
"\n",
"def H2_generator():\n",
" \n",
"\n",
" H = [\n",
" [-0.04207897647782277, 'i0'],\n",
" [0.17771287465139946, 'z0'],\n",
......@@ -399,7 +398,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......
......@@ -17,7 +17,7 @@
"\n",
"> Note that this tutorial is time-sensitive. And different computers will have individual differences. This tutorial does not guarantee that all computers can install it successfully.\n",
"\n",
"In deep learning, people usually use GPU for neural network model training because GPU has significant advantages in floating-point operations compared with CPU. Therefore, using GPU to train neural network models has gradually become a common choice. In Paddle Quantum, our quantum states and quantum gates are also represented by complex numbers based on floating-point numbers. If our model can be deployed on GPU for training, it will also significantly increase the training speed.\n"
"In deep learning, people usually use GPU for neural network model training because GPU has significant advantages in floating-point operations compared with CPU. Therefore, using GPU to train neural network models has gradually become a common choice. In Paddle Quantum, our quantum states and quantum gates are also represented by complex numbers based on floating-point numbers. If our model can be deployed on GPU for training, it will also significantly increase the training speed."
]
},
{
......@@ -142,7 +142,7 @@
"source": [
"We can enter `nvidia-smi` in the command line to view the usage of the GPU, including which programs are running on which GPUs, and its memory usage.\n",
"\n",
"Here, we take [VQE](https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/VQE) as an example to illustrate how we should use GPU. First, import the related packages and define some variables and functions."
"Here, we take [VQE](../tutorial/quantum_simulation/VQE_EN.ipynb) as an example to illustrate how we should use GPU. First, import the related packages and define some variables and functions."
]
},
{
......@@ -405,7 +405,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......
......@@ -29,8 +29,7 @@
"- 量子计算和量子神经网络的基础知识介绍\n",
"- 量桨(Paddle Quantum)的使用介绍\n",
"- 飞桨(PaddlePaddle)优化器的使用教程\n",
"- 具体的量子机器学习案例—— 变分量子特征求解器(VQE)\n",
"\n",
"- 具体的量子机器学习案例—— 变分量子本征求解器(VQE)\n",
"\n",
"最后修改于: 2021年3月2日 由量桨 Paddle Quantum 开发小组共同完成。\n",
"\n",
......@@ -128,8 +127,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:52:49.041480Z",
"start_time": "2021-03-09T03:52:43.796510Z"
"end_time": "2021-04-30T09:18:51.118039Z",
"start_time": "2021-04-30T09:18:47.681144Z"
}
},
"outputs": [],
......@@ -231,7 +230,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### 布洛赫球面 (Bloch Sphere) 表示\n",
"### 布洛赫球面表示\n",
"\n",
"我们用一个球面上的点来表示一个量子比特可能处于的量子态,这个球面被称为**布洛赫球面**(Bloch Sphere),(见图1)\n",
"\n",
......@@ -253,7 +252,6 @@
"**图 1.** \n",
"单量子比特的布洛赫球面表示. [[图片来源]](https://en.wikipedia.org/wiki/Qubit)\n",
"\n",
"\n",
"下面的内容面向对量子计算更熟悉的读者。如果你阅读这段感到困难,不用担心,您可以选择略过这一节,这不会对理解接下的内容产生影响。由于量子比特之间的交互以及去相干问题 (Decoherence),因此,对于一个具有多量子比特的系统来说,它的单量子比特子系统将不再处于纯态 (pure state),而是演变成混合态 (mixed state)。混合态可以看成不同纯态的按照一定概率的混合。 **单比特的混合态可以看成是布洛赫球内部的点,而不是存在于球表面**。通常来说,混合态需要用到量子力学的密度矩阵形式来描述,比如以下量子态分别有 $1/2$ 的概率处于 $|0\\rangle$ 或 $|1\\rangle$ 态,\n",
"\n",
"$$\n",
......@@ -263,14 +261,14 @@
"\n",
"其中行向量(bra)$\\langle0|$ 是列向量 (ket)$|0\\rangle$ 的复共轭转置。\n",
"\n",
"**注:** 如需更多信息,可参考维基百科 [链接](https://en.wikipedia.org/wiki/Qubit)\n"
"**注:** 如需更多信息,可参考维基百科 [链接](https://en.wikipedia.org/wiki/Qubit)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <a name=\"gate\">什么是量子逻辑门?</a>\n",
"### <a name=\"gate\">什么是量子逻辑门</a>\n",
"\n",
"在经典计算机中,我们可以在经典比特上施加基本的逻辑运算(非门 NOT, 与非门 NAND, 异或门 XOR, 与门 AND, 或门 OR)并组合成更复杂的运算。而量子计算则有完全不同的一套逻辑运算,它们被称为量子门 (quantum gate)。我们并不能在一个量子计算机上编译现有的C++程序。因为**经典计算机和量子计算机有不同的逻辑门构造,所以量子算法是需要利用这些量子门的特殊性来构造的**。量子门在数学上可以被表示成酉矩阵(unitary matrix)。酉矩阵操作可以保证向量的长度不变,这是个很好的性质。不然我们对一个纯态量子比特进行操作,会让它劣化成混合态导致其无法接着很好地使用。酉矩阵定义为:\n",
"\n",
......@@ -281,7 +279,7 @@
"\\tag{7}\n",
"$$\n",
"\n",
"其中 $U^{\\dagger}$ 是 $U$ 的 Hermite 转置,$I$ 表示单位矩阵。但是酉矩阵作为量子门的物理意义是什么?这意味着**所有的量子门都必须是可逆的**。对于任何一个量子门运算,都可以找到一个与其对应的反向运算。除此之外,酉矩阵必须是个方阵。因为量子门的输入和输出要求有同样数量的量子比特。一个作用在 $n$ 量子比特的量子门可以写成一个 $2^n \\times 2^n$ 的酉矩阵。最常见的(也是物理上最容易实现的)量子门作用在一个或两个量子比特上,就像经典逻辑门那样。"
"其中 $U^{\\dagger}$ 是 $U$ 的共轭转置,$I$ 表示单位矩阵。但是酉矩阵作为量子门的物理意义是什么?这意味着**所有的量子门都必须是可逆的**。对于任何一个量子门运算,都可以找到一个与其对应的反向运算。除此之外,酉矩阵必须是个方阵。因为量子门的输入和输出要求有同样数量的量子比特。一个作用在 $n$ 量子比特的量子门可以写成一个 $2^n \\times 2^n$ 的酉矩阵。最常见的(也是物理上最容易实现的)量子门作用在一个或两个量子比特上,就像经典逻辑门那样。"
]
},
{
......@@ -354,7 +352,7 @@
"source": [
"### 两比特量子门\n",
"\n",
"从单量子比特门我们可以拓展到两量子比特门。有两种拓展方式,第一种是只挑选出一个量子比特,在上面施加单量子比特门,其他的量子比特则不受影响。有的时候,您会见到如下图所示的量子电路:"
"从单量子比特门我们可以拓展到两量子比特门。有两种拓展方式,第一种是只挑选出一个量子比特,在上面施加单量子比特门,其他的量子比特则不进行任何操作。有的时候,会见到如下图所示的量子电路:"
]
},
{
......@@ -425,9 +423,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### <a name=\"measure\">什么是量子力学中的测量?</a>\n",
"### <a name=\"measure\">什么是量子力学中的测量</a>\n",
"\n",
"对于一个两分类的量子态,比如电子的自旋(Spin),可以自旋向上。这时我们规定该电子处于 $\\lvert {0}\\rangle$态。当然电子也可以自旋向下,这时我们规定它处于 $\\lvert {1}\\rangle$ 态。神奇的是,电子等微观粒子在被观测之前可以同时处于自旋向上和自旋向下的叠加态 $\\lvert {\\psi}\\rangle =\\alpha \\lvert {0}\\rangle + \\beta \\lvert {1}\\rangle$。那么这个奇怪的叠加态到底指的是什么呢?答案很简单,我们可以去测量一下这个处于\"叠加态\"的电子。值得注意的是,量子力学中的测量通常指的是一个统计结果而不是单次测量。这是由于测量本身的特性会使得观察后的量子态塌缩。就拿我们前面提到的处于 $\\lvert {\\psi}\\rangle$ 态的这个电子来举例,如果我们测量这一个电子的自旋,我们会有 $|\\alpha|^2$ 的概率观测到自旋向上并且观测后量子态塌缩成 $ \\lvert {0}\\rangle$。同样的,我们也有 $|\\beta|^2$ 的概率测量得到自旋向下$\\lvert {1}\\rangle$。那么想要精确的得到 $\\alpha$ 的数值,一次实验显然是不够的。我们需要拜托物理学家朋友准备了好多好多处于叠加态 $\\alpha \\lvert {0}\\rangle + \\beta \\lvert {1}\\rangle$ 的电子,把每一个电子的自旋都测量了一下再统计频率。测量在量子力学中地位比较特殊,如果读者觉得难理解。请参阅 [维基百科-量子力学中的测量](https://en.wikipedia.org/wiki/Measurement_in_quantum_mechanics#:~:text=In%20quantum%20physics%2C%20a%20measurement,makes%20are%20in%20general%20probabilistic.) 获取更多知识。\n",
"对于一个两分类的量子态,比如电子的自旋(Spin),我们规定该电子自旋向上 $\\uparrow$ 时记为 $|0\\rangle$ 态,自旋向下 $\\downarrow$ 时记为 $|1\\rangle$ 态。神奇的是,电子等微观粒子在被观测之前可以同时处于自旋向上和自旋向下的叠加态 $|\\psi\\rangle =\\alpha |0\\rangle + \\beta |1\\rangle$。那么这个叠加态到底指的是什么呢?答案很简单,我们可以去测量一下这个处于\"叠加态\"的电子。值得注意的是,量子力学中的测量通常指的是一个统计结果而不是单次测量。这是由于测量本身的特性会使得观察后的量子态塌缩。就拿我们前面提到的处于 $|\\psi\\rangle$ 态的这个电子来举例,如果我们测量这一个电子的自旋,我们会有 $|\\alpha|^2$ 的概率观测到自旋向上并且观测后量子态塌缩成 $ |0\\rangle$。同样的,我们也有 $|\\beta|^2$ 的概率测量得到自旋向下$|1\\rangle$。那么想要精确的得到 $\\alpha$ 的数值,一次实验显然是不够的。我们需要拜托物理学家朋友准备了好多好多处于叠加态 $\\alpha |0\\rangle + \\beta |1\\rangle$ 的电子,把每一个的自旋都测量再统计频率。测量在量子力学中地位比较特殊,如果读者觉得难理解。请参阅 [维基百科-量子力学中的测量](https://en.wikipedia.org/wiki/Measurement_in_quantum_mechanics#:~:text=In%20quantum%20physics%2C%20a%20measurement,makes%20are%20in%20general%20probabilistic.) 获取更多知识。\n",
"\n",
"<hr>"
]
......@@ -438,7 +436,7 @@
"source": [
"## <a name=\"ex1\">示例以及练习</a>\n",
"\n",
"### 示例: 用Paddle Quantum创建 $X$ 门\n",
"### 示例: 用 Paddle Quantum 创建 $X$ 门\n",
"\n",
"**注意:** 所有的单比特旋转门都按如下规定建立:\n",
"\n",
......@@ -471,8 +469,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:01.312586Z",
"start_time": "2021-03-09T03:53:01.145669Z"
"end_time": "2021-04-30T09:19:01.589007Z",
"start_time": "2021-04-30T09:19:01.468170Z"
}
},
"outputs": [
......@@ -588,25 +586,23 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### <a name=\"QNN\">示例: 如何创建量子神经网络 QNN?</a>\n",
"### <a name=\"QNN\">示例: 如何创建量子神经网络 QNN</a>\n",
"\n",
"QNN 通常可以表示为一些单比特量子旋转门和双比特门的组合。其中一个可以高效利用硬件的架构是只包含 $\\{R_x, R_y, R_z, \\text{CNOT}\\}$ 这四种量子门的模板。它们很容易在 NISQ (Noisy-Intermidiate-Scale-Quantum)设备(通常是超导量子比特)上实现,因为 $\\text{CNOT}$ 只需要实施在相邻量子比特上。一个例子可见下图:\n",
"\n",
"\n",
"![intro-fig-gate1](./figures/intro-fig-gate1.png)\n",
"\n",
"通常来说,每条线代表一个量子比特。我们把图最上端的认为是第一个量子比特 $q_0$,依次往下。从左到右代表我们施加门的时间顺序,先施加最左边的量子门。接下来,我们来看看如何在量桨上建造这个简单的两比特量子神经网络\n",
"\n",
"\n"
"通常来说,每条线代表一个量子比特。我们把图最上端的认为是第一个量子比特 $q_0$,依次往下。从左到右代表我们施加门的时间顺序,先施加最左边的量子门。接下来,我们来看看如何在量桨上建造这个简单的两比特量子神经网络"
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:07.533977Z",
"start_time": "2021-03-09T03:53:07.497242Z"
"end_time": "2021-04-30T09:19:07.433031Z",
"start_time": "2021-04-30T09:19:07.409641Z"
}
},
"outputs": [
......@@ -652,7 +648,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"$$ \\text{output} = \n",
"$$\n",
"\\text{output} = \n",
"\\begin{bmatrix} \n",
"0 &-1 &0 &0 \\\\ \n",
"-1 &0 &0 &0 \\\\\n",
......@@ -667,18 +664,18 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### 练习:\n",
"### 练习\n",
"\n",
"给你如下代码,你能想象出对应的电路吗?"
"给你如下代码,你能想象出对应的电路吗"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:09.041159Z",
"start_time": "2021-03-09T03:53:09.026637Z"
"end_time": "2021-04-30T09:19:17.518832Z",
"start_time": "2021-04-30T09:19:17.507574Z"
}
},
"outputs": [],
......@@ -716,6 +713,35 @@
"<img src=\"figures/intro-fig-gate2.png\" width=\"450\" >\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"也可以使用量桨中打印电路的功能查看构造好的电路:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--Ry(3.1416)----*----Ry(3.1416)----------------\n",
" | \n",
"--Ry(3.1416)----X---------*--------Ry(3.1416)--\n",
" | \n",
"--Ry(3.1416)--------------X--------Ry(3.1416)--\n",
" \n"
]
}
],
"source": [
"print(cir)"
]
},
{
"cell_type": "markdown",
"metadata": {},
......@@ -727,12 +753,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"在最新版本的 Paddle Quantum中,我们提供了一些内置的电路模板方便场景部署。"
"在最新版本的 Paddle Quantum 中,我们提供了一些内置的电路模板方便场景部署。"
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:12.042782Z",
......@@ -742,7 +768,7 @@
"outputs": [
{
"data": {
"image/png": "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\n",
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYgAAAEPCAYAAABY9lNGAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Z1A+gAAAACXBIWXMAAAsTAAALEwEAmpwYAAAZJElEQVR4nO3df5xddX3n8debn6JYfhmpkmhoidpQlGpEH+3WqijCY9VgBQ26FVwsdpVteai1cWtRqbuVVsW64tZ0URFXA0v9kS1RdEXrrhUkID8aIBL5GdQafiqyiJHP/nFOyM2dMzN3hty5l+T1fDzmMfee7zkz75k/5j3nfM+PVBWSJPXbadQBJEnjyYKQJHWyICRJnSwISVInC0KS1GmXUQfYVh73uMfVwoULRx1Dkh5RLrvsstural7X2HZTEAsXLmTNmjWjjiFJjyhJbp5szENMkqROFoQkqZMFIUnqZEFIkjpZEJKkThaEJKmTBSFJ6mRBSJI6WRCSpE7bzZXUD9fC5ReM7Hvf9L5/O+W42bqZbXbMNjuP5Gyz5R6EJKmTBSFJ6mRBSJI6WRCSpE5DLYgkRyZZl2R9kuUd489LcnmSTUmO6Vl+aJJvJ1mb5Kokrx5mTknSREMriCQ7A2cCRwGLgeOSLO5b7RbgBOAzfcvvA15XVQcDRwIfSrL3sLJKkiYa5mmuhwHrq+oGgCQrgaXANZtXqKqb2rEHezesqu/1vP5Bkh8D84C7h5hXktRjmIeYDgBu7Xm/oV02I0kOA3YDvt8xdlKSNUnWbNy4cdZBJUkTjfUkdZInAOcAr6+qB/vHq2pFVS2pqiXz5nU+UlWSNEvDLIjbgAU97+e3ywaS5FeAC4A/r6qLt3E2SdI0hlkQlwKLkhyYZDdgGbBqkA3b9T8PfKqqzh9iRknSJIZWEFW1CTgZuBC4FjivqtYmOS3JywGSPDvJBuBY4GNJ1rabvwp4HnBCkivaj0OHlVWSNNFQb9ZXVauB1X3LTu15fSnNoaf+7T4NfHqY2SRJUxvrSWpJ0uhYEJKkThaEJKmTBSFJ6mRBSJI6WRCSpE4WhCSpkwUhSepkQUiSOlkQkqROFoQkqZMFIUnqZEFIkjpZEJKkThaEJKmTBSFJ6mRBSJI6WRCSpE4WhCSpkwUhSepkQUiSOlkQkqROFoQkqZMFIUnqNNSCSHJkknVJ1idZ3jH+vCSXJ9mU5Ji+seOTXN9+HD/MnJKkiYZWEEl2Bs4EjgIWA8clWdy32i3ACcBn+rbdF3gX8BzgMOBdSfYZVlZJ0kTD3IM4DFhfVTdU1QPASmBp7wpVdVNVXQU82LftS4CvVtWdVXUX8FXgyCFmlST1GWZBHADc2vN+Q7tsm22b5KQka5Ks2bhx46yDSpImekRPUlfViqpaUlVL5s2bN+o4krRdGWZB3AYs6Hk/v1027G0lSdvAMAviUmBRkgOT7AYsA1YNuO2FwBFJ9mknp49ol0mS5sjQCqKqNgEn0/xhvxY4r6rWJjktycsBkjw7yQbgWOBjSda2294J/CVNyVwKnNYukyTNkV2G+cWrajWwum/ZqT2vL6U5fNS17ceBjw8znyRpco/oSWpJ0vBYEJKkThaEJKmTBSFJ6mRBSJI6WRCSpE4WhCSpkwUhSepkQUiSOlkQkqROFoQkqZMFIUnqZEFIkjpZEJKkThaEJKmTBSFJ6mRBSJI6WRCSpE4WhCSpkwUhSepkQUiSOlkQkqROFoQkqdNABZHkd5I8pn3975J8MMmThxtNkjRKg+5B/DfgviTPAN4KfB/41HQbJTkyybok65Ms7xjfPcm57fglSRa2y3dNcnaSq5Ncm+Qdg/9IkqRtYdCC2FRVBSwFPlJVZwKPnWqDJDsDZwJHAYuB45Is7lvtROCuqjoIOAM4vV1+LLB7VR0CPAt44+bykCTNjUEL4qftf/F/AFyQZCdg12m2OQxYX1U3VNUDwEqagum1FDi7fX0+cHiSAAU8JskuwB7AA8BPBswqSdoGBi2IVwM/B/59Vf0ImA/8zTTbHADc2vN+Q7usc52q2gTcA+xHUxY/A34I3AK8v6ru7P8GSU5KsibJmo0bNw74o0iSBjFQQbSl8A/A7u2i24HPDysUzd7HL4EnAgcCb03yax25VlTVkqpaMm/evCHGkaQdz6BnMf0hzX/1H2sXHQB8YZrNbgMW9Lyf3y7rXKc9nLQXcAfwGuDLVfWLqvox8C1gySBZJUnbxqCHmN4M/A7tPEBVXQ88fpptLgUWJTkwyW7AMmBV3zqrgOPb18cAF7WT4bcALwRoT699LnDdgFklSdvAoAXx83aiGXjov/2aaoN2TuFk4ELgWuC8qlqb5LQkL29XOwvYL8l64C3A5lNhzwT2TLKWpmg+UVVXDfpDSZIevl0GXO+fkvwnYI8kLwbeBPyv6TaqqtXA6r5lp/a8vp/mlNb+7e7tWi5JmjuD7kEsBzYCVwNvpPmj/85hhZIkjd5AexBV9SDw9+2HJGkHMGVBJDmvql6V5Go65hyq6ulDSyZJGqnp9iD+pP380mEHkSSNlynnIKrqh+3LN1XVzb0fNBPVkqTt1KCT1C/uWHbUtgwiSRov081B/AeaPYVfS9J7HcJjaa5uliRtp6abg/gM8CXgr9hyERvAT7tunidJ2n5MVxBVVTcleXP/QJJ9LQlJ2n4NsgfxUuAymtNc0zNWwIQ7rEqStg9TFkRVvbT9fODcxJEkjYvpJqmfOdV4VV2+beNIksbFdIeYPjDFWNHekluStP2Z7hDTC+YqiCRpvEx3iOmFVXVRkt/vGq+qzw0nliRp1KY7xPR7wEXAyzrGCrAgJGk7Nd0hpne1n18/N3EkSeNioHsxJdkvyYeTXJ7ksiR/m2S/YYeTJI3OoDfrW0nzRLlXAse0r88dVihJ0ugN+kzqJ1TVX/a8f2+SVw8jkCRpPAy6B/GVJMuS7NR+vAq4cJjBJEmjNd1prj9lyz2YTgE+3Q7tBNwLvG2Y4SRJozPdWUyPnasgkqTxMugcBEn2ARYBj9q8rKq+OYxQkqTRG/Q01zcA36SZd3hP+/ndA2x3ZJJ1SdYnWd4xvnuSc9vxS5Is7Bl7epJvJ1mb5Ookj+rfXpI0PINOUv8J8Gzg5vb+TL8F3D3VBkl2Bs6keXb1YuC4JIv7VjsRuKuqDgLOAE5vt92FZr7jj6rqYOD5wC8GzCpJ2gYGLYj7q+p+aP7rr6rrgKdOs81hwPqquqGqHqC5lmJp3zpLgbPb1+cDhycJcARwVVVdCVBVd1TVLwfMKknaBgYtiA1J9ga+AHw1yReBm6fZ5gDg1t6v0S7rXKeqNgH3APsBTwEqyYXt1dtv7/oGSU5KsibJmo0bNw74o0iSBjHQJHVVvaJ9+e4kXwf2Ar48tFRNrn9Dc1jrPuBrSS6rqq/15VoBrABYsmRJDTGPJO1wBt2DIMkzk/wx8HRgQ3vYaCq3AQt63s9vl3Wu08477AXcQbO38c2qur2q7gNWA1M+3U6StG0NehbTqTRzBfsBjwM+keSd02x2KbAoyYFJdgOWAav61lkFHN++Pga4qKqK5iypQ5I8ui2O3wOuGSSrJGnbGPQ6iNcCz+iZqH4fcAXw3sk2qKpNSU6m+WO/M/Dxqlqb5DRgTVWtAs4CzkmyHriTpkSoqruSfJCmZApYXVUXzOYHlCTNzqAF8QOaC+Tub9/vzsTDRRNU1Wqaw0O9y07teX0/cOwk236aLbf2kCTNsenuxfRfaf6DvwdYm+Sr7fsXA98ZfjxJ0qhMtwexpv18GfD5nuXfGEoaSdLYmO5mfZsvYqOdaH5K+3ZdVXllsyRtxwaag0jyfJqzmG6iufX3giTHe7M+Sdp+DTpJ/QHgiKpaB5DkKcBngWcNK5gkabQGvVBu183lAFBV3wN2HU4kSdI4GHQP4rIk/50tp52+li0T2JKk7dCgBfFHwJuBP27f/x/go0NJJEkaC9MWRPtchyur6mnAB4cfSZI0Dqadg2ifw7AuyZPmII8kaUwMeohpH5orqb8D/Gzzwqp6+VBSSZJGbtCC+IuhppAkjZ3p7sX0KJoJ6oOAq4Gz2ie/SZK2c9PNQZwNLKEph6NoLpiTJO0ApjvEtLiqDgFIchbewVWSdhjT7UE8dEM+Dy1J0o5luj2IZyT5Sfs6wB7t+wBVVb8y1HSSpJGZ7nbfO89VEEnSeBn0Zn2SpB2MBSFJ6mRBSJI6WRCSpE4WhCSpkwUhSeo01IJIcmSSdUnWJ1neMb57knPb8UuSLOwbf1KSe5O8bZg5JUkTDa0g2gcNnUlzD6fFwHFJFvetdiJwV1UdBJwBnN43/kHgS8PKKEma3DD3IA4D1lfVDVX1ALASWNq3zlKaGwICnA8cniQASY4GbgTWDjGjJGkSwyyIA4Bbe95vaJd1rtPe6+keYL8kewJ/Brxnqm+Q5KQka5Ks2bhx4zYLLkka30nqdwNnVNW9U61UVSuqaklVLZk3b97cJJOkHcSgT5SbjduABT3v57fLutbZkGQXYC/gDuA5wDFJ/hrYG3gwyf1V9ZEh5pUk9RhmQVwKLEpyIE0RLANe07fOKuB44NvAMcBFVVXA725eIcm7gXstB0maW0MriKralORk4EJgZ+DjVbU2yWnAmqpaBZwFnJNkPXAnTYlIksbAMPcgqKrVwOq+Zaf2vL4fOHaar/HuoYSTJE1pXCepJUkjZkFIkjpZEJKkThaEJKmTBSFJ6mRBSJI6WRCSpE4WhCSpkwUhSepkQUiSOlkQkqROFoQkqZMFIUnqZEFIkjpZEJKkThaEJKmTBSFJ6mRBSJI6WRCSpE4WhCSpkwUhSepkQUiSOlkQkqROFoQkqZMFIUnqNNSCSHJkknVJ1idZ3jG+e5Jz2/FLkixsl784yWVJrm4/v3CYOSVJEw2tIJLsDJwJHAUsBo5LsrhvtROBu6rqIOAM4PR2+e3Ay6rqEOB44Jxh5ZQkdRvmHsRhwPqquqGqHgBWAkv71lkKnN2+Ph84PEmq6rtV9YN2+VpgjyS7DzGrJKnPMAviAODWnvcb2mWd61TVJuAeYL++dV4JXF5VP+//BklOSrImyZqNGzdus+CSpDGfpE5yMM1hpzd2jVfViqpaUlVL5s2bN7fhJGk7N8yCuA1Y0PN+frusc50kuwB7AXe07+cDnwdeV1XfH2JOSVKHYRbEpcCiJAcm2Q1YBqzqW2cVzSQ0wDHARVVVSfYGLgCWV9W3hphRkjSJoRVEO6dwMnAhcC1wXlWtTXJakpe3q50F7JdkPfAWYPOpsCcDBwGnJrmi/Xj8sLJKkibaZZhfvKpWA6v7lp3a8/p+4NiO7d4LvHeY2SRJUxvrSWpJ0uhYEJKkThaEJKmTBSFJ6mRBSJI6WRCSpE4WhCSpkwUhSepkQUiSOlkQkqROFoQkqZMFIUnqZEFIkjpZEJKkThaEJKmTBSFJ6mRBSJI6WRCSpE4WhCSpkwUhSepkQUiSOlkQkqROFoQkqZMFIUnqNNSCSHJkknVJ1idZ3jG+e5Jz2/FLkizsGXtHu3xdkpcMM6ckaaKhFUSSnYEzgaOAxcBxSRb3rXYicFdVHQScAZzebrsYWAYcDBwJfLT9epKkOTLMPYjDgPVVdUNVPQCsBJb2rbMUOLt9fT5weJK0y1dW1c+r6kZgffv1JElzZJchfu0DgFt73m8AnjPZOlW1Kck9wH7t8ov7tj2g/xskOQk4qX17b5J12yb6jD0OuH22G+f0bZhkIrPNjtlmx2yzM8psT55sYJgFMXRVtQJYMeocSdZU1ZJR5+hittkx2+yYbXbGNdswDzHdBizoeT+/Xda5TpJdgL2AOwbcVpI0RMMsiEuBRUkOTLIbzaTzqr51VgHHt6+PAS6qqmqXL2vPcjoQWAR8Z4hZJUl9hnaIqZ1TOBm4ENgZ+HhVrU1yGrCmqlYBZwHnJFkP3ElTIrTrnQdcA2wC3lxVvxxW1m1g5Ie5pmC22THb7JhtdsYyW5p/2CVJ2ppXUkuSOlkQkqROFoQkqZMF8TAk2TfJvqPOIUnDYEHMUJInJVmZZCNwCfCdJD9uly0ccbyxl2T/JM9sP/YfdZ7pJNlz1BmkUfEsphlK8m3gQ8D5m0+9bW8keCxwSlU9d4TxJpXk6qo6ZITf/1Dg72guhtx80eN84G7gTVV1+WiSTS3JLVX1pDHIsT9bbjdzW1X96yjzDCLJnlV174gzhOY+bg/97oDv1Bj/4UvytKq6btQ5wIKYsSTXV9WimY7NhSS/P9kQ8HdVNW8u82wVILkCeGNVXdK3/LnAx6rqGSMJ1mR4y2RDwJ9X1cgOIz5SixVGX65JjgA+ClzP1r+7g2h+d18ZVbapjPr31usRfS+mEbksyUdp7kK7+WaEC2iuCP/uyFI1zgX+B9DV+o+a4yz9HtNfDgBVdXGSx4wiUI//AvwNzUWZ/UZ9GPaTTF6snwBGVqxtjqnKddSH5/4WeFFV3dS7sL07w2rgN0YRqs3w4cmGgL3nMMqULIiZex3Ncyzew9a7rZuvDB+lq4D3V9W/9A8kedEI8vT6UpILgE+xdbG+DvjyyFI1Lge+UFWX9Q8kecMI8vQa52KF8S7XXWjuBN3vNmDXOc7S7/XAW4Gfd4wdN8dZJuUhpu1Ikt8Fbq6qWzrGllTVmhHE6s1wFM2zPrYq1qpaPbpUkOSpwB1VNeF2y0n2H+Xx/vY/zV+nu1hvrKqTR5UNIMk/A/9xknK9taoWdGw2J5K8A3gVzbNoen93y4DzquqvRpjtIuCdVfXPHWM3VtWBI4g1gQUxQ+1dZ08EjmbrP3RfBM6qql+MKJq2U+NarPBQud5ZVRs7xkZarm2G36D7d3fN6FI1p8gD91fVfaPMMR0LYoaSfJZmgvBstuy+zqeZg9i3ql49omi95fUK4Int4rEvryQrquqk6dece+OcTRo2C2KGknyvqp4y07G5MOblNdmZQAGurKr5c5lnqwDjnW0v4B00/wXvT3MCwo9pSv99VXX3qLLBVvmOBh7PmOWbTJIvVdVRo87RZZyyOUk9c3cmORb4h6p6ECDJTjTXQdw10mTwrI6C2gBcnOR7owjUYyNwM80f3c2qff/4kSTaYpyznQdcBLygqn4EkORXgRPasSNGFw3Yku/5ffmOZ8T5kjxzsiHg0DmMMjHAGGfr5R7EDLVXS58OvIDmv3VoTkv7OrC8qm4cSTAgycXAB+gur7dUVf8zwecy2/XA4ZNMoI96MnOcs62rqqfOdGyujHO+JL8E/omti3+z51bVHnMc6SHjnK2XexAzVFU3JXk3zTUPW01Sj7IcWstoyuvMJHe3y/amKa9lI8q02YeAfYAJf4SBv57bKBN8iPHNdnOStwNnb57wba+qPoEtZ+aM0jjnu5bmGpLr+weSmG0A7kHMUJI/o/lju5Ktr85cBqysqveNKhtMetbGF6vq2tGlaiR5Gt1nlJhtEkn2AZbTZNt8uOtfaa67eV9VjfSw5jjnS3IMcHVVresYO7qqvjD3qR76/mObrZcFMUPtsfyD+88Iap+7vXbEt9oY2/Jq/8t8TZutdwLdbLOU5PVV9YlR55jMOOcz22AsiBlKch3wkqq6uW/5k4GvjPiY6ziXl9m2sXG6Z0+Xcc5ntsE4BzFzpwBfayc2Nx8rfBLNDcBGelUr8CDN9Q839y1/Qjs2SmabhSRXTTZEc9rrSI1zPrM9fBbEDFXVl5M8hYm3EL508+2/R+gUxre8TsFss7E/8BImnkIdYMJtGkZgnPOZ7WGyIGahPYX04lHn6DfO5WW2WftHYM+quqJ/IMk35jzNROOcz2wPk3MQkqROo74dryRpTFkQkqROFoR2WEnmJ/likuuT3JDkI0l2H2C7zucsJzlt84OZkpyS5NGTrPfSJN9NcmWSa5K8sV1+dJLFA3z/gdaTHi4LQjukJAE+R/MkuUXAImAPHsatNarq1Kr63+3bU4AJBZFkV2AF8LL2Ody/BXyjHT4aGOQP/6DrSQ+Lk9TaISU5HHhXVT2vZ9mv0FwLsQA4Bliy+YltSf6R5nGu32j3IP6e5k6lPwKWVdXGJJ+kOTvlicD7gXXA7VX1gp7vsS9wHfDkqvp/Pct/u932nvbjlcALgZOA3YD1wB/Q3Omzfz2AM4F5wH3AH1bVddvkF6UdmnsQ2lEdDGz1mMyq+glwE831D1N5DLCmqg6muSPnu/q+zoeBH9DcovsFfWN30tyn6OYkn03y2iQ7tY+eXAX8aVUdWlXfBz5XVc9u9zSuBU6cZL0VNI/9fBbwNuCjM/5tSB28DkKauQeBc9vXn6Y5VDWwqnpDkkOAF9H8QX8xzd1P+/1mkvfS3JF3T+DC/hWS7An8NvA/m6NmAEw7jyINwoLQjuoamsNID2kPMf0qzaGh32TrPexHTfG1ZnyctqquBq5Ocg5wI90F8Ung6Kq6MskJwPM71tkJuLuqDp1pBmk6HmLSjuprwKOTvA4gyc40D1v6SDs3cBNwaJKdkiygucp6s53YUi6vAf5vx9f/KfDY/oVJ9kzy/J5Fh7LlHlD92zwW+GE7sf3arq/dHha7sX3KIWk8Y6ofXBqUBaEdUjVnZ7wCOKa9B9MdwINV9Z/bVb5F85/9NcCHgct7Nv8ZcFiSf6GZSD6t41usAL6c5Ot9ywO8Pcm6JFcA72HL3sNK4E/bU2B/HfgL4JI2S++kc/96rwVOTHIlsJbm2QzSw+ZZTBIPnUX0WeAVVXX5dOtLOwILQpLUyUNMkqROFoQkqZMFIUnqZEFIkjpZEJKkThaEJKnT/weRuZs3hsDuNQAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -772,7 +798,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:12.698149Z",
......@@ -782,7 +808,7 @@
"outputs": [
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -814,7 +840,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"以下是一个使用频率较高的电路模板 `complex_entangled_layer(theta, DEPTH)`,用户可按照电路深度参数 `DEPTH/D` 快速拓展电路。其中涉及的广义旋转门 $U_3$ 的定义为:\n",
"以下是一个使用频率较高的电路模板 `complex_entangled_layer(theta, DEPTH)`,用户可按照电路深度参数 `DEPTH` 快速拓展电路。其中涉及的广义旋转门 $U_3$ 的定义为\n",
"\n",
"$$\n",
"U_3(\\theta, \\phi, \\varphi) := \n",
......@@ -824,7 +850,7 @@
"\\end{bmatrix},\\tag{20}\n",
"$$\n",
"\n",
"$U_3$ 旋转门在效果上是等价于以下组合旋转门的,\n",
"$U_3$ 旋转门在效果上是等价于以下组合旋转门的\n",
"\n",
"$$\n",
"U_3(\\theta, \\phi, \\varphi) \n",
......@@ -848,12 +874,12 @@
"\n",
"<img src=\"figures/intro-fig-complex_entangled_layer2-cn.png\" width=\"850\" >\n",
"\n",
"特别地,当我们处理的任务不涉及虚数时,使用电路模板 `real_entangled_layer(theta, DEPTH)` 会更加高效 ($R_y$旋转门替代$U_3$)。"
"特别地,当我们处理的任务不涉及虚数时,使用电路模板 `real_entangled_layer(theta, DEPTH)` 会更加高效($R_y$ 旋转门替代 $U_3$)。"
]
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:14.040033Z",
......@@ -864,7 +890,7 @@
"outputs": [
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -919,16 +945,18 @@
"source": [
"### <a name=\"vec\"> 波函数向量模式 </a>\n",
"\n",
"所谓的波函数模式也就是用复数向量表示和储存量子态。向量模式只能处理纯态,但这种模式在家用电脑硬件高效支持**20+量子比特**的运算。用户可以测试下自己电脑的极限在哪里。在这种表示下,量子门 (酉矩阵)作用在量子比特 (一个复向量)上本质上的运算是**矩阵乘以向量**:\n",
"所谓的波函数模式也就是用复数向量表示和储存量子态。向量模式只能处理纯态,但这种模式在家用电脑硬件高效支持 **20+ 量子比特**的运算。用户可以测试下自己电脑的极限在哪里。在这种表示下,量子门(酉矩阵)作用在量子比特(一个复向量表示其所处状态)上本质上的运算是**矩阵乘以向量**:\n",
"\n",
"$$\\lvert {\\psi}\\rangle = U \\lvert {\\psi_0}\\rangle. \\tag{22}$$\n",
"$$\n",
"\\lvert {\\psi}\\rangle = U \\lvert {\\psi_0}\\rangle. \\tag{22}\n",
"$$\n",
"\n",
"代码中,具体体现在 UAnsatz的调用 `cir.run_state_vector(input_state = None)`。如果我们不输入任何初始量子态,就会默认所有的量子比特都处于$\\lvert {0}\\rangle$态。接着来看个具体的例子:"
"代码中,具体体现在 UAnsatz的调用 `cir.run_state_vector(input_state = None)`。如果我们不输入任何初始量子态,就会默认所有的量子比特都处于 $\\lvert {0}\\rangle$ 态。接着来看个具体的例子:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:27.327236Z",
......@@ -940,8 +968,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[[ 0.00034024+0.j -0.00015082+0.j 0.00038722+0.j ... -0.00041021+0.j\n",
" -0.00070034+0.j -0.00021523+0.j]]\n"
"[[ 9.65721758e-05+0.j -4.38538841e-04+0.j 2.68195580e-05+0.j ...\n",
" -4.32163794e-04+0.j -6.48040560e-05+0.j 1.52848347e-04+0.j]]\n"
]
}
],
......@@ -979,16 +1007,18 @@
"source": [
"### <a name=\"density\"> 密度矩阵模式 </a>\n",
"\n",
"同时 Paddle quantum也支持了密度矩阵运算模式,也就是用一个密度矩阵 $\\rho = \\sum_i P_i \\lvert {\\psi_i}\\rangle\\langle{\\psi_i} \\lvert$表示和储存量子态。该模式下可以根据算法需要支持**混合态模拟**。但是在密度矩阵模式下,家用电脑硬件只能运行10个左右的量子比特。请用户注意这方面的限制,我们也在不断优化这个模式下的模拟器性能。在这种表示下,量子门 (酉矩阵)作用在量子态(一个迹为1的厄尔米特矩阵)上本质上的运算是**矩阵乘法**:\n",
"同时 Paddle quantum也支持了密度矩阵运算模式,也就是用一个密度矩阵 $\\rho = \\sum_i P_i \\lvert {\\psi_i}\\rangle\\langle{\\psi_i} \\lvert$ 表示和储存量子态。该模式下可以根据算法需要支持**混合态模拟**。但是在密度矩阵模式下,家用电脑硬件只能运行10个左右的量子比特。请用户注意这方面的限制,我们也在不断优化这个模式下的模拟器性能。在这种表示下,量子门 (酉矩阵)作用在量子态(一个迹为1的厄尔米特矩阵)上本质上的运算是**矩阵乘法**:\n",
"\n",
"$$\\rho = U \\rho_0 U^\\dagger. \\tag{23}$$\n",
"$$\n",
"\\rho = U \\rho_0 U^\\dagger. \\tag{23}\n",
"$$\n",
"\n",
"代码中,具体体现在 UAnsatz的调用 `cir.run_density_matrix()`。接着来看个具体的例子:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 10,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:27.433188Z",
......@@ -1000,10 +1030,10 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[[ 0.04269908+0.j 0.01452372+0.j 0.15539789+0.j -0.12851626+0.j]\n",
" [ 0.01452372+0.j 0.00494012+0.j 0.05285723+0.j -0.04371368+0.j]\n",
" [ 0.15539789+0.j 0.05285723+0.j 0.56555089+0.j -0.4677186 +0.j]\n",
" [-0.12851626+0.j -0.04371368+0.j -0.4677186 +0.j 0.38680991+0.j]]\n"
"[[ 0.56503575+0.j 0.44320439+0.j -0.13063786+0.j 0.17964958+0.j]\n",
" [ 0.44320439+0.j 0.34764194+0.j -0.10247011+0.j 0.14091406+0.j]\n",
" [-0.13063786+0.j -0.10247011+0.j 0.03020384+0.j -0.04153549+0.j]\n",
" [ 0.17964958+0.j 0.14091406+0.j -0.04153549+0.j 0.05711846+0.j]]\n"
]
}
],
......@@ -1037,20 +1067,13 @@
"print(final_state.numpy())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"如果你对源代码有兴趣,可以利用如下 magic command即时查看。或者关注我们的 [[Github]](https://github.com/PaddlePaddle/Quantum)!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <a name=\"Bell\">练习:如何从计算基制备贝尔态</a>\n",
"\n",
"贝尔态是一种很常用的量子纠缠态, 可以表示为\n",
"贝尔态是一种很常用的量子纠缠态,可以表示为\n",
"\n",
"$$\n",
"\\lvert {\\Phi^+}\\rangle = \\frac{1}{\\sqrt{2}} \\big(\\lvert {00}\\rangle + \\lvert {11}\\rangle\\big)\n",
......@@ -1063,7 +1086,7 @@
"\\end{bmatrix}.\\tag{24}\n",
"$$\n",
"\n",
"那么我们如何用量桨来制备一个贝尔态呢? 只需要如下的量子电路:\n"
"那么我们如何用量桨来制备一个贝尔态呢?只需要如下的量子电路:"
]
},
{
......@@ -1075,7 +1098,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 11,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:27.924758Z",
......@@ -1085,7 +1108,7 @@
"outputs": [
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -1151,15 +1174,15 @@
"\n",
"$$\n",
"\\mathcal{L}(\\theta_1, \\theta_2, \\theta_3)\n",
"= (\\theta_1)^2 + (\\theta_2)^2 + (\\theta_3)^2 + 10 \\tag{25}\n",
"= (\\theta_1)^2 + (\\theta_2)^2 + (\\theta_3)^2 + 10. \\tag{25}\n",
"$$\n",
"\n",
"可以看出,只有当 $\\theta_1 = \\theta_2 = \\theta_3 = 0$ 的时候,$\\mathcal{L}$ 取最小值10。\n"
"可以看出,只有当 $\\theta_1 = \\theta_2 = \\theta_3 = 0$ 的时候,$\\mathcal{L}$ 取最小值 $10$。"
]
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 12,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:47.622260Z",
......@@ -1230,19 +1253,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### <a name=\"ex2\"> 练习: 本征值寻找</a>\n",
"\n",
"### <a name=\"ex2\"> 练习: 特征值寻找</a>\n",
"\n",
"接下来,我们试一个更复杂的损失函数。 首先我们介绍一个随机的埃尔米特矩阵 $H$ 其**特征值**为矩阵 $D$ 的对角元素。 \n",
"\n",
"$$ D = \\begin{bmatrix} 0.2 &0 \\\\ 0 &0.8 \\end{bmatrix}, \\tag{26} $$\n",
"接下来,我们试一个更复杂的损失函数。首先我们介绍一个随机的埃尔米特矩阵 $H$,其**本征值**为矩阵 $D$ 的对角元素, \n",
"\n",
"不用担心,我们会帮你生成这个埃尔米特矩阵$H$. \n",
"$$\n",
"D = \\begin{bmatrix} 0.2 &0 \\\\ 0 &0.8 \\end{bmatrix}, \\tag{26}\n",
"$$\n",
"\n",
"然后我们初始化参数向量$\\boldsymbol{\\theta}$,构造出一个简单的线性运算 $U(\\boldsymbol{\\theta}) = R_z(\\theta_1)*R_y(\\theta_2)*R_z(\\theta_3)$\n",
"不用担心,我们会帮你生成这个埃尔米特矩阵 $H$。\n",
"\n",
"然后我们初始化参数向量$\\boldsymbol{\\theta}$,构造出一个简单的线性运算 $U(\\boldsymbol{\\theta}) = R_z(\\theta_1)*R_y(\\theta_2)*R_z(\\theta_3)$:\n",
"\n",
"$$ \n",
"$$\n",
"U(\\theta_1, \\theta_2, \\theta_3) = \n",
"\\begin{bmatrix}\n",
"e^{-i\\frac{\\theta_1}{2}} & 0 \\\\ \n",
......@@ -1258,14 +1281,13 @@
"\\end{bmatrix}, \\tag{27}\n",
"$$\n",
"\n",
"我们让这个矩阵(模板)乘以 $\\lvert {0}\\rangle$,得到一个新的2维复向量$\\lvert {\\phi}\\rangle$\n",
"\n",
"我们让这个矩阵(模板)乘以 $\\lvert {0}\\rangle$,得到一个新的 2 维复向量\n",
"\n",
"$$ \n",
"\\lvert {\\phi}\\rangle = U(\\theta_1, \\theta_2, \\theta_3)\\lvert {0}\\rangle, \\tag{28}\n",
"$$\n",
"\n",
"然后,我们定义损失函数为\n",
"然后,我们定义损失函数为\n",
"\n",
"$$\n",
"\\mathcal{L}(\\theta_1, \\theta_2, \\theta_3) \n",
......@@ -1278,7 +1300,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 13,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:50.904606Z",
......@@ -1291,10 +1313,10 @@
"output_type": "stream",
"text": [
"随机生成的矩阵 H 是:\n",
"[[ 0.63841338-6.93889390e-18j -0.13697062-2.28212151e-01j]\n",
" [-0.13697062+2.28212151e-01j 0.36158662+0.00000000e+00j]] \n",
"[[0.65531213+0.00000000e+00j 0.00378707+2.56639434e-01j]\n",
" [0.00378707-2.56639434e-01j 0.34468787+1.21430643e-17j]] \n",
"\n",
"不出所料,H 的征值是:\n",
"不出所料,H 的征值是:\n",
"[0.2 0.8]\n"
]
}
......@@ -1305,7 +1327,7 @@
"# V 是一个 2x2 的随机酉矩阵\n",
"V = unitary_group.rvs(2)\n",
"\n",
"# D 的对角元是H的征值\n",
"# D 的对角元是H的征值\n",
"# 你可以任意改变这里的对角元数值\n",
"D = np.diag([0.2, 0.8])\n",
"\n",
......@@ -1316,13 +1338,13 @@
"H = (V @ D @ V_dagger)\n",
"print('随机生成的矩阵 H 是:')\n",
"print(H, '\\n')\n",
"print('不出所料,H 的征值是:')\n",
"print('不出所料,H 的征值是:')\n",
"print(np.linalg.eigh(H)[0])"
]
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 14,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:50.916504Z",
......@@ -1354,7 +1376,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 15,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:54.556150Z",
......@@ -1391,7 +1413,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 16,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:53:59.114893Z",
......@@ -1403,17 +1425,17 @@
"name": "stdout",
"output_type": "stream",
"text": [
"iter: 0 loss: 0.6550\n",
"iter: 5 loss: 0.4527\n",
"iter: 10 loss: 0.2951\n",
"iter: 15 loss: 0.2330\n",
"iter: 20 loss: 0.2108\n",
"iter: 25 loss: 0.2033\n",
"iter: 30 loss: 0.2010\n",
"iter: 35 loss: 0.2003\n",
"iter: 40 loss: 0.2001\n",
"iter: 0 loss: 0.2878\n",
"iter: 5 loss: 0.2202\n",
"iter: 10 loss: 0.2044\n",
"iter: 15 loss: 0.2010\n",
"iter: 20 loss: 0.2003\n",
"iter: 25 loss: 0.2001\n",
"iter: 30 loss: 0.2000\n",
"iter: 35 loss: 0.2000\n",
"iter: 40 loss: 0.2000\n",
"iter: 45 loss: 0.2000\n",
"损失函数的最小值是: 0.20000807961972783\n"
"损失函数的最小值是: 0.2000001964593201\n"
]
}
],
......@@ -1450,11 +1472,13 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"我们可以改变一下$H$的特征值。如果将它对角化后的的对角矩阵改变为\n",
"我们可以改变一下 $H$ 的本征值。如果将它对角化后的的对角矩阵改变为\n",
"\n",
"$$ D = \\begin{bmatrix} 0.8 &0 \\\\ 0 &1.2 \\end{bmatrix}. \\tag{30} $$\n",
"$$\n",
"D = \\begin{bmatrix} 0.8 &0 \\\\ 0 &1.2 \\end{bmatrix}, \\tag{30}\n",
"$$\n",
"\n",
"你会发现我们仍然得到了$H$的最小特征值0.8, 你能找到背后的原因吗?还是说这背后隐藏着什么理论?\n"
"你会发现我们仍然得到了 $H$ 的最小本征值 $0.8$。你能找到背后的原因吗?还是说这背后隐藏着什么理论?"
]
},
{
......@@ -1477,13 +1501,15 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### <a name=\"VQE\"> 变分量子特征求解器 (VQE) -- 无监督学习</a>\n",
"### <a name=\"VQE\"> 变分量子本征求解器——无监督学习</a>\n",
"\n",
"目前阶段,大规模的可容错的量子计算机还未实现。我们目前只能造出有噪音的,中等规模量子计算系统(NISQ)。现在一个利用 NISQ 的量子设备很有前景的算法种类就是量子-经典混合算法。人们期望这套方法也许可以在某些应用中超越经典计算机的表现。变分量子特征求解器(VQE)就是里面的一个重要应用。它利用参数化的电路搜寻广阔的希尔伯特空间,并利用经典机器学习中的梯度下降来找到最优参数,并接近一个哈密顿量的基态(也就是找到一个埃尔米特矩阵的最小特征值)。为了确保你能理解, 我们来一起过一遍以下两量子比特 (2-qubit)的例子。\n",
"目前阶段,大规模的可容错的量子计算机还未实现。我们目前只能造出有噪音的,中等规模量子计算系统(NISQ)。现在一个利用 NISQ 的量子设备很有前景的算法种类就是量子-经典混合算法。人们期望这套方法也许可以在某些应用中超越经典计算机的表现。变分量子本征求解器(Variational Quantum Eigensolver, VQE)就是里面的一个重要应用。它利用参数化的电路搜寻广阔的希尔伯特空间,并利用经典机器学习中的梯度下降来找到最优参数,并接近一个哈密顿量的基态(也就是找到一个埃尔米特矩阵的最小本征值)。为了确保你能理解, 我们来一起过一遍以下两量子比特 (2-qubit)的例子。\n",
"\n",
"假设我们想找到如下哈密顿量的基态:\n",
"\n",
"$$ H = 0.4 \\, Z \\otimes I + 0.4 \\, I \\otimes Z + 0.2 \\, X \\otimes X. \\tag{31}$$\n",
"$$\n",
"H = 0.4 \\, Z \\otimes I + 0.4 \\, I \\otimes Z + 0.2 \\, X \\otimes X. \\tag{31}\n",
"$$\n",
"\n",
"给定一种常见的量子神经网络架构"
]
......@@ -1499,12 +1525,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"我们已经学会如何建造这个电路了。如果你忘了, 请转到 <a href=\"#QNN\">这里</a>。"
"我们已经学会如何建造这个电路了。如果需要复习,请转到 <a href=\"#QNN\">这里</a>。"
]
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 17,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:54:03.717323Z",
......@@ -1533,7 +1559,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 18,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:54:04.655091Z",
......@@ -1577,7 +1603,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 19,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:54:17.622644Z",
......@@ -1602,7 +1628,7 @@
"iter: 30 loss: -0.8101\n",
"iter: 40 loss: -0.8154\n",
"iter: 50 loss: -0.8225\n",
"计算得到的基态能量是: -0.824229008050201\n",
"计算得到的基态能量是: -0.8242290080502013\n",
"真实的基态能量为: -0.8246211251235321\n"
]
}
......@@ -1703,7 +1729,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.10"
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
......@@ -1721,7 +1747,7 @@
"width": "426.667px"
},
"toc_section_display": true,
"toc_window_display": true
"toc_window_display": false
},
"varInspector": {
"cols": {
......
......@@ -114,8 +114,7 @@
"\n",
"The row vector (bra) $\\langle0| = |0\\rangle^\\dagger$ is the conjugate transpose of the column vector (ket) $|0\\rangle$.\n",
"\n",
"**Note:** For more information, please refer to [Wikipedia](https://en.wikipedia.org/wiki/Qubit).\n",
"\n"
"**Note:** For more information, please refer to [Wikipedia](https://en.wikipedia.org/wiki/Qubit)."
]
},
{
......@@ -198,7 +197,7 @@
"\n",
"We can expand the idea of single-qubit gates to multi-qubit. There are two ways to realize this expansion. The first is to apply single-qubit gates on selected qubits, while the other qubits are not operated. The figure below gives a concrete example:\n",
"\n",
"![intro-fig-hadamard](./figures/intro-fig-hadamard.png \"**Figure 2.** Circuit representation and interpretation of two-qubit logic operations. [[Picture source]](https://en.wikipedia.org/wiki/Quantum_logic_gate)\")\n",
"![intro-fig-hadamard](./figures/intro-fig-hadamard.png \"**Figure 2.** Circuit representation and interpretation of two-qubit logic operations. [[Image source]](https://en.wikipedia.org/wiki/Quantum_logic_gate)\")\n",
"\n",
"The quantum gate acting on two-qubit system can be expressed as a $4\\times4$ unitary matrix\n",
"\n",
......@@ -286,9 +285,7 @@
"\\tag{16}\n",
"$$\n",
"\n",
"Therefore, it is not difficult to see that the $X$ gate can be expressed as $R_x(\\pi)$. The following code will generate the $X$ gate:\n",
"\n",
"\n"
"Therefore, it is not difficult to see that the $X$ gate can be expressed as $R_x(\\pi)$. The following code will generate the $X$ gate:"
]
},
{
......@@ -296,8 +293,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:55:14.848783Z",
"start_time": "2021-03-09T03:55:10.779109Z"
"end_time": "2021-04-30T09:20:08.888161Z",
"start_time": "2021-04-30T09:20:05.709738Z"
}
},
"outputs": [
......@@ -374,8 +371,7 @@
"ExecuteTime": {
"end_time": "2021-03-09T03:55:00.653853Z",
"start_time": "2021-03-09T03:55:00.404797Z"
},
"scrolled": true
}
},
"outputs": [],
"source": [
......@@ -427,11 +423,11 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:55:17.952285Z",
"start_time": "2021-03-09T03:55:17.912517Z"
"end_time": "2021-04-30T09:20:13.355621Z",
"start_time": "2021-04-30T09:20:13.331839Z"
}
},
"outputs": [
......@@ -486,8 +482,7 @@
"0 &0 &0 &1 \n",
"\\end{bmatrix}.\n",
"\\tag{19}\n",
"$$\n",
"\n"
"$$"
]
},
{
......@@ -501,11 +496,11 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:55:18.945226Z",
"start_time": "2021-03-09T03:55:18.935212Z"
"end_time": "2021-04-30T09:20:15.796777Z",
"start_time": "2021-04-30T09:20:15.786887Z"
}
},
"outputs": [],
......@@ -535,8 +530,41 @@
"source": [
"Answer:\n",
"\n",
"![intro-fig-gate2](./figures/intro-fig-gate2.png)\n",
"\n"
"![intro-fig-gate2](./figures/intro-fig-gate2.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can print your circuit using Paddle Quantum as follows:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-30T09:20:18.642677Z",
"start_time": "2021-04-30T09:20:18.636895Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--Ry(3.142)----*----Ry(3.142)---------------\n",
" | \n",
"--Ry(3.142)----X--------*--------Ry(3.142)--\n",
" | \n",
"--Ry(3.142)-------------X--------Ry(3.142)--\n",
" \n"
]
}
],
"source": [
"print(cir)"
]
},
{
......@@ -667,8 +695,7 @@
"\n",
"![intro-fig-complex_entangled_layer2](./figures/intro-fig-complex_entangled_layer2.png)\n",
"\n",
"When our task does not involve imaginary numbers, it is more efficient to use the circuit template `real_entangled_layer(theta, DEPTH)` ($R_y$ instead of $U_3$).\n",
"\n"
"When our task does not involve imaginary numbers, it is more efficient to use the circuit template `real_entangled_layer(theta, DEPTH)` ($R_y$ instead of $U_3$)."
]
},
{
......@@ -795,8 +822,7 @@
"\\tag{23}\n",
"$$\n",
"\n",
"Function `cir.run_density_matrix()` will be used in the following code. Here is an example:\n",
"\n"
"Function `cir.run_density_matrix()` will be used in the following code. Here is an example:"
]
},
{
......@@ -1460,7 +1486,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
......@@ -1478,7 +1504,7 @@
"width": "580px"
},
"toc_section_display": true,
"toc_window_display": true
"toc_window_display": false
},
"varInspector": {
"cols": {
......
......@@ -31,7 +31,7 @@ def H_generator():
# Generate Pauli string representing a specific Hamiltonian
H = [[-1.0, 'z0,z1'], [-1.0, 'z1,z2'], [-1.0, 'z0,z2']]
# Generate the marix form of the Hamiltonian
# Generate the matrix form of the Hamiltonian
N_SYS_B = 3 # Number of qubits in subsystem B used to generate Gibbs state
hamiltonian = pauli_str_to_matrix(H, N_SYS_B)
......
......@@ -17,7 +17,6 @@ Paddle_GIBBS
"""
from numpy import pi as PI
import paddle
from paddle import matmul, trace
from paddle_quantum.circuit import UAnsatz
......
......@@ -17,7 +17,6 @@ main
"""
import scipy
import paddle
from numpy import trace as np_trace
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.GIBBS.Paddle_GIBBS import Paddle_GIBBS
......@@ -27,7 +26,7 @@ def main():
# Generate Pauli string representing a specific Hamiltonian
H = [[-1.0, 'z0,z1'], [-1.0, 'z1,z2'], [-1.0, 'z0,z2']]
# Generate the marix form of the Hamiltonian
# Generate the matrix form of the Hamiltonian
N_SYS_B = 3 # Number of qubits in subsystem B used to generate Gibbs state
hamiltonian = pauli_str_to_matrix(H, N_SYS_B)
......
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Paddle_QAOA: To learn more about the functions and properties of this application,
you could check the corresponding Jupyter notebook under the Tutorial folder.
"""
import paddle
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.QAOA.QAOA_Prefunc import Generate_H_D, Generate_default_graph
from paddle_quantum.QAOA.QAOA_Prefunc import Draw_benchmark
from paddle_quantum.QAOA.QAOA_Prefunc import Draw_cut_graph, Draw_original_graph
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
# Random seed for optimizer
SEED = 1024
__all__ = [
"circuit_QAOA",
"Net",
"Paddle_QAOA",
]
def circuit_QAOA(E, V, n, p, gamma, beta):
"""
This function constructs the parameterized QAOA circuit which is composed of P layers of two blocks:
one block is based on the problem Hamiltonian H which encodes the classical problem,
and the other is constructed from the driving Hamiltonian describing the rotation around Pauli X
acting on each qubit. It outputs the final state of the QAOA circuit.
Args:
E: edges of the graph
V: vertices of the graph
n: number of qubits in th QAOA circuit
p: number of layers of two blocks in the QAOA circuit
gamma: parameter to be optimized in the QAOA circuit, parameter for the first block
beta: parameter to be optimized in the QAOA circui, parameter for the second block
Returns:
the QAOA circuit
"""
cir = UAnsatz(n)
cir.superposition_layer()
for layer in range(p):
for (u, v) in E:
cir.cnot([u, v])
cir.rz(gamma[layer], v)
cir.cnot([u, v])
for v in V:
cir.rx(beta[layer], v)
return cir
class Net(paddle.nn.Layer):
"""
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.
"""
def __init__(
self,
p,
dtype="float64",
):
super(Net, self).__init__()
self.p = p
self.gamma = self.create_parameter(shape = [self.p],
default_initializer = paddle.nn.initializer.Uniform(
low = 0.0,
high = 2 * np.pi
),
dtype = dtype,
is_bias = False)
self.beta = self.create_parameter(shape = [self.p],
default_initializer = paddle.nn.initializer.Uniform(
low = 0.0,
high = 2 * np.pi
),
dtype = dtype, is_bias = False)
def forward(self, n, E, V, H_D_list):
cir = circuit_QAOA(E, V, n, self.p, self.gamma, self.beta)
cir.run_state_vector()
loss = -cir.expecval(H_D_list)
return loss, cir
def Paddle_QAOA(n, p, E, V, H_D_list, ITR, LR):
"""
This is the core function to run QAOA.
Args:
n: number of qubits (default value N=4)
E: edges of the graph
V: vertices of the graph
p: number of layers of blocks in the QAOA circuit (default value p=4)
ITR: number of iteration steps for QAOA (default value ITR=120)
LR: learning rate for the gradient-based optimization method (default value LR=0.1)
Returns:
the optimized QAOA circuit
summary_iter
summary_loss
"""
net = Net(p)
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
summary_iter, summary_loss = [], []
for itr in range(1, ITR + 1):
loss, cir = net(n, E, V, H_D_list)
loss.backward()
opt.minimize(loss)
opt.clear_grad()
if itr % 10 == 0:
print("iter:", itr, " loss:", "%.4f" % loss.numpy())
summary_loss.append(loss[0][0].numpy())
summary_iter.append(itr)
gamma_opt = net.gamma.numpy()
print("优化后的参数 gamma:\n", gamma_opt)
beta_opt = net.beta.numpy()
print("优化后的参数 beta:\n", beta_opt)
return cir, summary_iter, summary_loss
def main(n = 4, E = None):
paddle.seed(SEED)
p = 4 # number of layers in the circuit
ITR = 120 #number of iterations
LR = 0.1 #learning rate
if E is None:
G, V, E = Generate_default_graph(n)
else:
G = nx.Graph()
V = range(n)
G.add_nodes_from(V)
G.add_edges_from(E)
Draw_original_graph(G)
#construct the Hamiltonia
H_D_list, H_D_matrix = Generate_H_D(E, n)
H_D_diag = np.diag(H_D_matrix).real
H_max = np.max(H_D_diag)
H_min = -H_max
print(H_D_diag)
print('H_max:', H_max, ' H_min:', H_min)
cir, summary_iter, summary_loss = Paddle_QAOA(n, p, E, V, H_D_list, ITR, LR)
H_min = np.ones([len(summary_iter)]) * H_min
Draw_benchmark(summary_iter, summary_loss, H_min)
prob_measure = cir.measure(plot=True)
cut_bitstring = max(prob_measure, key=prob_measure.get)
print("找到的割的比特串形式:", cut_bitstring)
Draw_cut_graph(V, E, G, cut_bitstring)
if __name__ == "__main__":
n = int(input("Please input the number of vertices: "))
user_input_edge_flag = int(input("Please choose if you want to input edges yourself (0 for yes, 1 for no): "))
if user_input_edge_flag == 1:
main(n)
else:
E = []
prompt = "Please input tuples indicating edges (e.g., (0, 1)), input 'z' if finished: "
while True:
edge = input(prompt)
if edge == 'z':
main(n, E)
break
else:
edge = eval(edge)
E.append(edge)
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Aid func
"""
import matplotlib.pyplot as plt
import numpy as np
import networkx as nx
from paddle_quantum.utils import pauli_str_to_matrix
def Draw_original_graph(G):
"""
This is to draw the original graph
Args:
G: the constructed graph
Returns:
Null
"""
pos = nx.circular_layout(G)
options = {
"with_labels": True,
"font_size": 20,
"font_weight": "bold",
"font_color": "white",
"node_size": 2000,
"width": 2
}
nx.draw_networkx(G, pos, **options)
ax = plt.gca()
ax.margins(0.20)
plt.axis("off")
plt.show()
return
def Draw_cut_graph(V, E, G, cut_bitstring):
"""
This is to draw the graph after cutting
Args:
V: vertices in the graph
E: edges in the graph
cut_bitstring: bit string indicate whether vertices belongs to the first group or the second group
Returns:
Null
"""
node_cut = ["blue" if cut_bitstring[v] == "1" else "red" for v in V]
edge_cut = [
"solid" if cut_bitstring[u] == cut_bitstring[v] else "dashed"
for (u, v) in G.edges()
]
pos = nx.circular_layout(G)
options = {
"with_labels": True,
"font_size": 20,
"font_weight": "bold",
"font_color": "white",
"node_size": 2000,
"width": 2
}
nx.draw(
G,
pos,
node_color = node_cut,
style = edge_cut,
**options
)
ax = plt.gca()
ax.margins(0.20)
plt.axis("off")
plt.show()
return
def Generate_default_graph(n):
"""
This is to generate a default graph if no input
Args:
n: number of vertices
Returns:
G: the graph
E: edges list
V: vertices list
"""
G = nx.Graph()
V = range(n)
G.add_nodes_from(V)
E = []
for i in range(n - 1):
E.append((i, i + 1))
E.append((0, n - 1))
G.add_edges_from(E)
return G, V, E
def Generate_H_D(E, n):
"""
This is to construct Hamiltonia H_D
Args:
E: edges of the graph
Returns:
Hamiltonia list
Hamiltonia H_D
"""
H_D_list = []
for (u, v) in E:
H_D_list.append([-1.0, 'z' + str(u) + ',z' + str(v)])
print(H_D_list)
H_D_matrix = pauli_str_to_matrix(H_D_list, n)
return H_D_list, H_D_matrix
def Draw_benchmark(summary_iter, summary_loss, H_min):
"""
This is draw the learning tendency, and difference bwtween it and the benchmark
Args:
summary_iter: indicate which iteration
summary_loss: indicate the energy of that iteration
H_min: benchmark value H_min
Returns:
NULL
"""
plt.figure(1)
loss_QAOA, = plt.plot(
summary_iter,
summary_loss,
alpha=0.7,
marker='',
linestyle="--",
linewidth=2,
color='m')
benchmark, = plt.plot(
summary_iter,
H_min,
alpha=0.7,
marker='',
linestyle=":",
linewidth=2,
color='b')
plt.xlabel('Number of iteration')
plt.ylabel('Performance of the loss function for QAOA')
plt.legend(
handles=[loss_QAOA, benchmark],
labels=[
r'Loss function $\left\langle {\psi \left( {\bf{\theta }} \right)} '
r'\right|H\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $',
'The benchmark result',
],
loc='best')
# Show the picture
plt.show()
return
def main():
# number of qubits or number of nodes in the graph
n = 4
G, V, E = Generate_default_graph(n)
Draw_original_graph(G)
if __name__ == "__main__":
main()
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Benchmark
"""
from matplotlib import pyplot
from numpy import diag, max, min, load, ones
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator
def benchmark_QAOA(classical_graph_adjacency=None, N=None):
"""
This function benchmarks the performance of QAOA. Indeed, it compares its approximate solution obtained
from QAOA with predetermined parameters, such as iteration step = 120 and learning rate = 0.1, to the exact solution
to the classical problem.
"""
# Generate the graph and its adjacency matrix from the classical problem, such as the Max-Cut problem
if all(var is None for var in (classical_graph_adjacency, N)):
N = 4
_, classical_graph_adjacency = generate_graph(N, 1)
# Convert the Hamiltonian's list form to matrix form
H_matrix = pauli_str_to_matrix(H_generator(N, classical_graph_adjacency), N)
H_diag = diag(H_matrix).real
# Compute the exact solution of the original problem to benchmark the performance of QAOA
H_max = max(H_diag)
H_min = min(H_diag)
print('H_max:', H_max, ' H_min:', H_min)
# Load the data of QAOA
x1 = load('./output/summary_data.npz')
H_min = ones([len(x1['iter'])]) * H_min
# Plot it
pyplot.figure(1)
loss_QAOA, = pyplot.plot(x1['iter'], x1['energy'],
alpha=0.7, marker='', linestyle="--", linewidth=2, color='m')
benchmark, = pyplot.plot(
x1['iter'],
H_min,
alpha=0.7,
marker='',
linestyle=":",
linewidth=2,
color='b')
pyplot.xlabel('Number of iteration')
pyplot.ylabel('Performance of the loss function for QAOA')
pyplot.legend(
handles=[loss_QAOA, benchmark],
labels=[
r'Loss function $\left\langle {\psi \left( {\bf{\theta }} \right)} '
r'\right|H\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $',
'The benchmark result',
],
loc='best')
# Show the picture
pyplot.show()
def main():
"""
main
"""
benchmark_QAOA()
if __name__ == '__main__':
main()
......@@ -17,39 +17,60 @@ main
"""
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
import paddle
from paddle_quantum.QAOA.QAOA_Prefunc import Generate_H_D, Draw_cut_graph, Draw_original_graph, Generate_default_graph
from paddle_quantum.QAOA.Paddle_QAOA import Paddle_QAOA
from paddle_quantum.QAOA.maxcut import maxcut_hamiltonian, find_cut
from paddle_quantum.utils import pauli_str_to_matrix
SEED = 1024
options = {
"with_labels": True,
"font_size": 20,
"font_weight": "bold",
"font_color": "white",
"node_size": 2000,
"width": 2
}
def main(n = 4):
def main(n=4):
paddle.seed(SEED)
p = 4 # number of layers in the circuit
ITR = 120 #number of iterations
LR = 0.1 #learning rate
p = 4 # number of layers in the circuit
ITR = 120 # number of iterations
LR = 0.1 # learning rate
G, V, E = Generate_default_graph(n)
G.add_nodes_from(V)
G.add_edges_from(E)
Draw_original_graph(G)
G = nx.cycle_graph(4)
V = list(G.nodes())
E = list(G.edges())
# Draw the original graph
pos = nx.circular_layout(G)
nx.draw_networkx(G, pos, **options)
ax = plt.gca()
ax.margins(0.20)
plt.axis("off")
plt.show()
#construct the Hamiltonia
H_D_list, H_D_matrix = Generate_H_D(E, n)
# construct the Hamiltonian
H_D_list = maxcut_hamiltonian(E)
H_D_matrix = pauli_str_to_matrix(H_D_list, n)
H_D_diag = np.diag(H_D_matrix).real
H_max = np.max(H_D_diag)
print(H_D_diag)
print('H_max:', H_max)
cir, _, _ = Paddle_QAOA(n, p, E, V, H_D_list, ITR, LR)
prob_measure = cir.measure(plot=True)
cut_bitstring = max(prob_measure, key=prob_measure.get)
print("找到的割的比特串形式:", cut_bitstring)
cut_bitstring, _ = find_cut(G, p, ITR, LR, print_loss=True, plot=True)
print("The bit string form of the cut found:", cut_bitstring)
node_cut = ["blue" if cut_bitstring[v] == "1" else "red" for v in V]
edge_cut = ["solid" if cut_bitstring[u] == cut_bitstring[v] else "dashed" for (u, v) in G.edges()]
Draw_cut_graph(V, E, G, cut_bitstring)
nx.draw(G, pos, node_color = node_cut, style=edge_cut, **options)
ax = plt.gca()
ax.margins(0.20)
plt.axis("off")
plt.show()
if __name__ == "__main__":
......
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
To learn more about the functions and properties of this application,
you could check the corresponding Jupyter notebook under the Tutorial folder.
"""
import paddle
from paddle_quantum.circuit import UAnsatz
import numpy as np
import networkx as nx
__all__ = [
"maxcut_hamiltonian",
"circuit_maxcut",
"find_cut",
]
def maxcut_hamiltonian(E):
r"""生成最大割问题对应的哈密顿量。
Args:
E (list): 图的边
Returns:
list: 生成的哈密顿量的列表形式
"""
H_D_list = []
for (u, v) in E:
H_D_list.append([-1.0, 'z' + str(u) + ',z' + str(v)])
return H_D_list
def circuit_maxcut(E, V, p, gamma, beta):
r"""构建用于最大割问题的 QAOA 参数化电路。
Args:
E: 图的边
V: 图的顶点
p: QAOA 电路的层数
gamma: 与最大割问题哈密顿量相关的电路参数
beta: 与混合哈密顿量相关的电路参数
Returns:
UAnsatz: 构建好的 QAOA 电路
"""
# Number of qubits needed
n = len(V)
cir = UAnsatz(n)
cir.superposition_layer()
for layer in range(p):
for (u, v) in E:
cir.cnot([u, v])
cir.rz(gamma[layer], v)
cir.cnot([u, v])
for i in V:
cir.rx(beta[layer], i)
return cir
class _MaxcutNet(paddle.nn.Layer):
"""
It constructs the net for maxcut which combines the QAOA circuit with the classical optimizer that sets rules
to update parameters described by theta introduced in the QAOA circuit.
"""
def __init__(
self,
p,
dtype="float64",
):
super(_MaxcutNet, self).__init__()
self.p = p
self.gamma = self.create_parameter(shape=[self.p],
default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),
dtype=dtype, is_bias=False)
self.beta = self.create_parameter(shape=[self.p],
default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),
dtype=dtype, is_bias=False)
def forward(self, E, V, H_D_list):
"""
Forward propagation
"""
cir = circuit_maxcut(E, V, self.p, self.gamma, self.beta)
cir.run_state_vector()
loss = -cir.expecval(H_D_list)
return loss, cir
def find_cut(G, p, ITR, LR, print_loss=False, shots=0, plot=False):
r"""运行 QAOA 寻找最大割问题的近似解。
Args:
G (NetworkX graph): 图
p (int): QAOA 电路的层数
ITR (int): 梯度下降优化参数的迭代次数
LR (float): Adam 优化器的学习率
print_loss (bool, optional): 优化过程中是否输出损失函数的值,默认为 ``False``,即不输出
shots (int, optional): QAOA 电路最终输出的量子态的测量次数,默认 0,则返回测量结果的精确概率分布
plot (bool, optional): 是否绘制测量结果图,默认为 ``False`` ,即不绘制
Returns:
tuple: tuple containing:
string: 寻找到的近似解
dict: 所有测量结果和其对应的出现次数
"""
V = list(G.nodes())
# Map nodes' labels to integers from 0 to |V|-1
# node_mapping = {V[i]:i for i in range(len(V))}
# G_mapped = nx.relabel_nodes(G, node_mapping)
G_mapped = nx.convert_node_labels_to_integers(G)
V = list(G_mapped.nodes())
E = list(G_mapped.edges())
n = len(V)
H_D_list = maxcut_hamiltonian(E)
net = _MaxcutNet(p)
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
for itr in range(1, ITR + 1):
loss, cir = net(E, V, H_D_list)
loss.backward()
opt.minimize(loss)
opt.clear_grad()
if print_loss and itr % 10 == 0:
print("iter:", itr, " loss:", "%.4f" % loss.numpy())
prob_measure = cir.measure(shots=shots, plot=plot)
cut_bitstring = max(prob_measure, key=prob_measure.get)
return cut_bitstring, prob_measure
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Travelling Salesman Problem (TSP): To learn more about the functions and properties of this application,
you could check the corresponding Jupyter notebook under the Tutorial folder.
"""
from itertools import permutations
import numpy as np
import networkx as nx
import paddle
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import pauli_str_to_matrix
__all__ = [
"tsp_hamiltonian",
"solve_tsp",
"solve_tsp_brute_force"
]
def tsp_hamiltonian(g, A, n):
"""
This is to construct Hamiltonia H_C
Args:
G: the graph to solve
Returns:
Hamiltonian list
Hamiltonian H_C
"""
H_C_list1 = []
for i in range(n - 1):
for j in range(n - 1):
if i != j:
w_ij = g[i][j]['weight']
for t in range(n - 2):
H_C_list1.append([w_ij / 4, 'i1'])
H_C_list1.append([w_ij / 4, 'z' + str(i * (n - 1) + t) + ',z' + str(j * (n - 1) + t + 1)])
H_C_list1.append([-w_ij / 4, 'z' + str(i * (n - 1) + t)])
H_C_list1.append([-w_ij / 4, 'z' + str(j * (n - 1) + t + 1)])
H_C_list1.append([g[n - 1][i]['weight'] / 2, 'i1'])
H_C_list1.append([-g[n - 1][i]['weight'] / 2, 'z' + str(i * (n - 1) + (n - 2))])
H_C_list1.append([g[i][n - 1]['weight'] / 2, 'i1'])
H_C_list1.append([-g[i][n - 1]['weight'] / 2, 'z' + str(i * (n - 1))])
H_C_list2 = []
for i in range(n - 1):
H_C_list2.append([1, 'i1'])
for t in range(n-1):
H_C_list2.append([-2 * 1/2, 'i1'])
H_C_list2.append([2 * 1/2, 'z' + str(i * (n - 1) + t)])
H_C_list2.append([2/4, 'i1'])
H_C_list2.append([-2/4, 'z' + str(i * (n - 1) + t)])
for tt in range(t):
H_C_list2.append([2/4, 'i1'])
H_C_list2.append([2/4, 'z' + str(i * (n - 1) + t) + ',z' + str(i * (n - 1) + tt)])
H_C_list2.append([-2/4, 'z' + str(i * (n - 1) + t)])
H_C_list2.append([-2/4, 'z' + str(i * (n - 1) + tt)])
H_C_list2 = [[A * c, s] for (c, s) in H_C_list2]
H_C_list3 = []
for t in range(n - 1):
H_C_list3.append([1, 'i1'])
for i in range(n-1):
H_C_list3.append([-2 * 1/2, 'i1'])
H_C_list3.append([2 * 1/2, 'z' + str(i * (n - 1) + t)])
H_C_list3.append([2/4, 'i1'])
H_C_list3.append([-2/4, 'z' + str(i * (n - 1) + t)])
for ii in range(i):
H_C_list3.append([2/4, 'i1'])
H_C_list3.append([2/4, 'z' + str(i * (n - 1) + t) + ',z' + str(ii * (n - 1) + t)])
H_C_list3.append([-2/4,'z'+str(i * (n - 1) + t)])
H_C_list3.append([-2/4,'z'+str(ii * (n - 1) + t)])
H_C_list3 = [[A * c, s] for (c, s) in H_C_list3]
H_C_list = H_C_list1 + H_C_list2 + H_C_list3
return H_C_list
class _TSPNet(paddle.nn.Layer):
"""
It constructs the net for TSP which combines the complex entangled circuit with the classical optimizer that sets rules
to update parameters described by theta introduced in the circuit.
"""
def __init__(self, n, p, dtype="float64"):
super(_TSPNet, self).__init__()
self.p = p
self.num_qubits = (n - 1) ** 2
self.theta = self.create_parameter(shape=[self.p, self.num_qubits, 3],
default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),
dtype=dtype, is_bias=False)
def forward(self, H_C_ls):
"""
Forward propagation
"""
cir = UAnsatz(self.num_qubits)
cir.complex_entangled_layer(self.theta, self.p)
cir.run_state_vector()
loss = cir.expecval(H_C_ls)
return loss, cir
def solve_tsp(g, A, p=2, ITR=120, LR=0.4, print_loss=False, shots=0):
"""
This is the core function to solve the TSP.
Args:
g: the graph to solve
A: the penality parameter
p: number of layers of blocks in the complex entangled circuit (default value p=2)
ITR: number of iteration steps for the complex entangled circuit (default value ITR=120)
LR: learning rate for the gradient-based optimization method (default value LR=0.4)
Returns:
string representation for the optimized walk for the salesman
"""
e = list(g.edges(data = True))
v = list(g.nodes)
n = len(v)
H_C_list = tsp_hamiltonian(g, A, n)
net = _TSPNet(n, p)
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
for itr in range(1, ITR + 1):
loss, cir = net(H_C_list)
loss.backward()
opt.minimize(loss)
opt.clear_grad()
if print_loss and itr % 10 == 0:
print("iter:", itr, "loss:", "%.4f"% loss.numpy())
prob_measure = cir.measure(shots=shots)
reduced_salesman_walk = max(prob_measure, key=prob_measure.get)
str_by_vertex = [reduced_salesman_walk[i:i + n - 1] for i in range(0, len(reduced_salesman_walk) + 1, n - 1)]
salesman_walk = '0'.join(str_by_vertex) + '0' * (n - 1) + '1'
return salesman_walk
def solve_tsp_brute_force(g):
"""
This is the brute-force algorithm to solve the TSP.
Args:
g: the graph to solve
Returns:
the list of the optimized walk in the visiting order and the optimal distance
"""
n = len(g.nodes)
all_routes = list(permutations(range(n)))
best_distance = 1e10
best_route = (0, 0, 0, 0)
for route in all_routes:
distance = 0
for i in range(n):
u = route[i]
v = route[(i + 1) % n]
distance += g[u][v]['weight']
if distance < best_distance:
best_distance = distance
best_route = route
return list(best_route), best_distance
......@@ -17,8 +17,6 @@ main
"""
import numpy
import paddle
from paddle_quantum.SSVQE.HGenerator import H_generator
from paddle_quantum.SSVQE.Paddle_SSVQE import Paddle_SSVQE
......
......@@ -18,7 +18,6 @@ benchmark the result
import platform
import matplotlib.pyplot as plt
import numpy
from paddle_quantum.utils import pauli_str_to_matrix
......
......@@ -28,7 +28,6 @@ __all__ = [
]
# todo
def Hamiltonian_str_convert(qubit_op):
'''
Convert provided Hamiltonian information to Pauli string
......
......@@ -17,8 +17,6 @@ main
"""
import platform
import paddle
from paddle_quantum.VQE.Paddle_VQE import Paddle_VQE
from paddle_quantum.VQE.benchmark import benchmark_result
from paddle_quantum.VQE.chemistrysub import H2_generator
......
......@@ -16,7 +16,7 @@
HGenerator
"""
from numpy import diag
import numpy
import scipy
import scipy.stats
......@@ -26,13 +26,13 @@ __all__ = ["generate_rho_sigma", ]
def generate_rho_sigma():
scipy.random.seed(SEED)
V = scipy.stats.unitary_group.rvs(4) # Generate a random unitary martrix
D = diag([0.5, 0.3, 0.1, 0.1]) # Input the spectrum of the target state rho
numpy.random.seed(SEED)
V = scipy.stats.unitary_group.rvs(4) # Generate a random unitary matrix
D = numpy.diag([0.5, 0.3, 0.1, 0.1]) # Input the spectrum of the target state rho
V_H = V.conj().T
rho = V @ D @ V_H # Generate rho
# print(rho) # Print quantum state rho
# Input the quantum state sigma
sigma = diag([0.1, 0.2, 0.3, 0.4]).astype('complex128')
sigma = numpy.diag([0.1, 0.2, 0.3, 0.4]).astype('complex128')
return rho, sigma
......@@ -17,8 +17,6 @@ Main
"""
import numpy
import paddle
from paddle_quantum.VQSD.HGenerator import generate_rho_sigma
from paddle_quantum.VQSD.Paddle_VQSD import Paddle_VQSD
......
......@@ -17,4 +17,4 @@ Paddle Quantum Library
"""
name = "paddle_quantum"
__version__ = "2.0.1"
__version__ = "2.1.0"
......@@ -12,15 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import gc
import math
import warnings
import numpy as np
import math
from functools import reduce
from collections import defaultdict
import numpy as np
import matplotlib.pyplot as plt
from paddle_quantum.simulator import transfer_state, init_state_gen, measure_state
import paddle
from paddle import matmul, trace, real, imag, reshape
from paddle_quantum.utils import dagger, pauli_str_to_matrix
......@@ -55,7 +53,152 @@ class UAnsatz:
self.__run_state = ''
# Record history of adding gates to the circuit
self.__history = []
def _count_history(self):
r"""calculate how many blocks needed for printing
Note:
这是内部函数,你并不需要直接调用到该函数。
"""
# Record length of each section
length = [5]
n = self.n
# Record current section number for every qubit
qubit = [0] * n
# Number of sections
qubit_max = max(qubit)
# Record section number for each gate
gate = []
history = self.__history
for current_gate in history:
# Single-qubit gates with no params to print
if current_gate[0] in {'h', 's', 't', 'x', 'y', 'z', 'u'}:
curr_qubit = current_gate[1][0]
gate.append(qubit[curr_qubit])
qubit[curr_qubit] = qubit[curr_qubit] + 1
# A new section is added
if qubit[curr_qubit] > qubit_max:
length.append(5)
qubit_max = qubit[curr_qubit]
# Gates with params to print
elif current_gate[0] in {'rx', 'ry', 'rz'}:
curr_qubit = current_gate[1][0]
gate.append(qubit[curr_qubit])
if length[qubit[curr_qubit]] == 5:
length[qubit[curr_qubit]] = 13
qubit[curr_qubit] = qubit[curr_qubit] + 1
if qubit[curr_qubit] > qubit_max:
length.append(5)
qubit_max = qubit[curr_qubit]
# Two-qubit gates
elif current_gate[0] in {'CNOT', 'SWAP', 'RXX_gate', 'RYY_gate', 'RZZ_gate', 'MS_gate'}:
p = current_gate[1][0]
q = current_gate[1][1]
a = max(p, q)
b = min(p, q)
ind = max(qubit[b: a + 1])
gate.append(ind)
if length[ind] < 13 and current_gate[0] in {'RXX_gate', 'RYY_gate', 'RZZ_gate'}:
length[ind] = 13
for j in range(b, a + 1):
qubit[j] = ind + 1
if ind + 1 > qubit_max:
length.append(5)
qubit_max = ind + 1
return length, gate
def __str__(self):
r"""实现画电路的功能
Returns:
string: 用来print的字符串
代码示例:
.. code-block:: python
import paddle
from paddle_quantum.circuit import UAnsatz
import numpy as np
cir = UAnsatz(5)
cir.superposition_layer()
rotations = paddle.to_tensor(np.random.uniform(-2, 2, size=(3, 5, 1)))
cir.real_entangled_layer(rotations, 3)
print(cir)
::
The printed circuit is:
--H----Ry(-0.14)----*-------------------X----Ry(-0.77)----*-------------------X--
| | | |
--H----Ry(-1.00)----X----*--------------|----Ry(-0.83)----X----*--------------|--
| | | |
--H----Ry(-1.88)---------X----*---------|----Ry(-0.98)---------X----*---------|--
| | | |
--H----Ry(1.024)--------------X----*----|----Ry(-0.37)--------------X----*----|--
| | | |
--H----Ry(1.905)-------------------X----*----Ry(-1.82)-------------------X----*--
"""
length, gate = self._count_history()
history = self.__history
n = self.n
# Ignore the unused section
total_length = sum(length) - 5
print_list = [['-' if i % 2 == 0 else ' '] * total_length for i in range(n * 2)]
for i, current_gate in enumerate(history):
if current_gate[0] in {'h', 's', 't', 'x', 'y', 'z', 'u'}:
# Calculate starting position ind of current gate
sec = gate[i]
ind = sum(length[:sec])
print_list[current_gate[1][0] * 2][ind + length[sec] // 2] = current_gate[0].upper()
elif current_gate[0] in {'rx', 'ry', 'rz'}:
sec = gate[i]
ind = sum(length[:sec])
line = current_gate[1][0] * 2
param = current_gate[2][2 if current_gate[0] == 'rz' else 0]
print_list[line][ind + 2] = 'R'
print_list[line][ind + 3] = current_gate[0][1]
print_list[line][ind + 4] = '('
print_list[line][ind + 5: ind + 10] = format(float(param.numpy()), '.3f')[:5]
print_list[line][ind + 10] = ')'
elif current_gate[0] in {'CNOT', 'SWAP', 'RXX_gate', 'RYY_gate', 'RZZ_gate', 'MS_gate'}:
sec = gate[i]
ind = sum(length[:sec])
cqubit = current_gate[1][0]
tqubit = current_gate[1][1]
if current_gate[0] in {'CNOT', 'SWAP'}:
print_list[cqubit * 2][ind + length[sec] // 2] = '*'
print_list[tqubit * 2][ind + length[sec] // 2] = 'X' if current_gate[0] == 'CNOT' else '*'
elif current_gate[0] == 'MS_gate':
for qubit in {cqubit, tqubit}:
print_list[qubit * 2][ind + length[sec] // 2 - 1] = 'M'
print_list[qubit * 2][ind + length[sec] // 2] = '_'
print_list[qubit * 2][ind + length[sec] // 2 + 1] = 'S'
elif current_gate[0] in {'RXX_gate', 'RYY_gate', 'RZZ_gate'}:
param = current_gate[2]
for line in {cqubit * 2, tqubit * 2}:
print_list[line][ind + 2] = 'R'
print_list[line][ind + 3: ind + 5] = current_gate[0][1:3].lower()
print_list[line][ind + 5] = '('
print_list[line][ind + 6: ind + 10] = format(float(param.numpy()), '.2f')[:4]
print_list[line][ind + 10] = ')'
start_line = min(cqubit, tqubit)
end_line = max(cqubit, tqubit)
for k in range(start_line * 2 + 1, end_line * 2):
print_list[k][ind + length[sec] // 2] = '|'
print_list = list(map(''.join, print_list))
return_str = '\n'.join(print_list)
return return_str
def run_state_vector(self, input_state=None, store_state=True):
r"""运行当前的量子电路,输入输出的形式为态矢量。
......@@ -94,7 +237,7 @@ class UAnsatz:
The output state vector is [[0.62054458+0.j 0.18316521+0.28526291j 0.62054458+0.j 0.18316521+0.28526291j]]
"""
# Throw a warning when cir has channel
if self.__has_channel == True:
if self.__has_channel:
warnings.warn('The noiseless circuit will be run.', RuntimeWarning)
state = init_state_gen(self.n, 0) if input_state is None else input_state
old_shape = state.shape
......@@ -153,7 +296,7 @@ class UAnsatz:
state = paddle.to_tensor(density_op(self.n)) if input_state is None else input_state
assert state.shape == [2 ** self.n, 2 ** self.n], "The dimension is not right"
if self.__has_channel == False:
if not self.__has_channel:
state = matmul(self.U, matmul(state, dagger(self.U)))
else:
dim = 2 ** self.n
......@@ -169,7 +312,7 @@ class UAnsatz:
# Combine preceding unitary operations
unitary = transfer_by_history(identity, self.__history[u_start:i])
sub_state = paddle.zeros(shape, dtype='complex128')
# sum all the terms corresponding to different Kraus operators
# Sum all the terms corresponding to different Kraus operators
for op in history_ele[1]:
pseudo_u = reshape(transfer_state(unitary, op, history_ele[2]), shape)
sub_state += pseudo_u @ state @ dagger(pseudo_u)
......@@ -218,7 +361,7 @@ class UAnsatz:
[ 0.70710678+0.j 0. +0.j -0.70710678+0.j 0. +0.j]]
"""
# Throw a warning when cir has channel
if self.__has_channel == True:
if self.__has_channel:
warnings.warn('The unitary matrix of the noiseless circuit will be given.', RuntimeWarning)
dim = 2 ** self.n
shape = (dim, dim)
......@@ -230,6 +373,116 @@ class UAnsatz:
return reshape(state, shape)
def basis_encoding(self, x, invert=False):
r"""将输入的经典数据使用基态编码的方式编码成量子态。
在 basis encoding 中,输入的经典数据只能包括 0 或 1。如输入数据为 1101,则编码后的量子态为 :math:`|1101\rangle` 。
这里假设量子态在编码前为全 0 的态,即 :math:`|00\ldots 0\rangle` 。
Args:
x (Tensor): 待编码的向量
invert (bool): 添加的是否为编码电路的逆电路,默认为 ``False`` ,即添加正常的编码电路
"""
x = paddle.flatten(x)
x = paddle.cast(x, dtype="int32")
assert x.size == self.n, "the number of classical data should be equal to the number of qubits"
for idx, element in enumerate(x):
if element:
self.x(idx)
def amplitude_encoding(self, x, mode):
r"""将输入的经典数据使用振幅编码的方式编码成量子态。
Args:
x (Tensor): 待编码的向量
mode (str): 生成的量子态的表示方式,``"state_vector"`` 代表态矢量表示, ``"density_matrix"`` 代表密度矩阵表示
Returns:
Tensor: 一个形状为 ``(2 ** n, )`` 或 ``(2 ** n, 2 ** n)`` 的张量,表示编码之后的量子态。
"""
assert x.size <= 2 ** self.n, "the number of classical data should be equal to the number of qubits"
x = paddle.flatten(x)
pad_num = 2 ** self.n - x.size
if pad_num > 0:
zero_tensor = paddle.zeros((pad_num,), x.dtype)
x = paddle.concat([x, zero_tensor])
length = paddle.norm(x, p=2)
x = paddle.divide(x, length)
if mode == "state_vector":
x = paddle.cast(x, dtype="complex128")
elif mode == "density_matrix":
x = paddle.reshape(x, (2**self.n, 1))
x = matmul(x, dagger(x))
else:
raise ValueError("the mode should be state_vector or density_matrix")
return x
def angle_encoding(self, x, encoding_gate, invert=False):
r"""将输入的经典数据使用角度编码的方式进行编码。
Args:
x (Tensor): 待编码的向量
encoding_gate (str): 编码要用的量子门,可以是 ``"rx"`` 、 ``"ry"`` 和 ``"rz"``
invert (bool): 添加的是否为编码电路的逆电路,默认为 ``False`` ,即添加正常的编码电路
"""
assert x.size <= self.n, "the number of classical data should be equal to the number of qubits"
x = paddle.flatten(x)
if invert:
x = -x
def add_encoding_gate(theta, idx, gate):
if gate == "rx":
self.rx(theta, idx)
elif gate == "ry":
self.ry(theta, idx)
elif gate == "rz":
self.rz(theta, idx)
else:
raise ValueError("the encoding_gate should be rx, ry, or rz")
for idx, element in enumerate(x):
add_encoding_gate(element[0], idx, encoding_gate)
def iqp_encoding(self, x, num_repeats=1, pattern=None, invert=False):
r"""将输入的经典数据使用 IQP 编码的方式进行编码。
Args:
x (Tensor): 待编码的向量
num_repeats (int): 编码层的层数
pattern (list): 量子比特的纠缠方式
invert (bool): 添加的是否为编码电路的逆电路,默认为 ``False`` ,即添加正常的编码电路
"""
assert x.size <= self.n, "the number of classical data should be equal to the number of qubits"
num_x = x.size
x = paddle.flatten(x)
if pattern is None:
pattern = list()
for idx0 in range(0, self.n):
for idx1 in range(idx0 + 1, self.n):
pattern.append((idx0, idx1))
while num_repeats > 0:
num_repeats -= 1
if invert:
for item in pattern:
self.cnot(list(item))
self.rz(-x[item[0]]*x[item[1]], item[1])
self.cnot(list(item))
for idx in range(0, num_x):
self.rz(-x[idx], idx)
for idx in range(0, num_x):
self.h(idx)
else:
for idx in range(0, num_x):
self.h(idx)
for idx in range(0, num_x):
self.rz(x[idx], idx)
for item in pattern:
self.cnot(list(item))
self.rz(x[item[0]]*x[item[1]], item[1])
self.cnot(list(item))
"""
Common Gates
"""
......@@ -260,10 +513,10 @@ class UAnsatz:
cir.rx(theta[0], which_qubit)
"""
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['u', [which_qubit], [theta,
paddle.to_tensor(np.array([-math.pi / 2])),
paddle.to_tensor(np.array([math.pi / 2]))]])
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n (the number of qubit)"
self.__history.append(['rx', [which_qubit], [theta,
paddle.to_tensor(np.array([-math.pi / 2])),
paddle.to_tensor(np.array([math.pi / 2]))]])
def ry(self, theta, which_qubit):
r"""添加关于 y 轴的单量子比特旋转门。
......@@ -290,10 +543,10 @@ class UAnsatz:
which_qubit = 0
cir.ry(theta[0], which_qubit)
"""
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['u', [which_qubit], [theta,
paddle.to_tensor(np.array([0.0])),
paddle.to_tensor(np.array([0.0]))]])
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n (the number of qubit)"
self.__history.append(['ry', [which_qubit], [theta,
paddle.to_tensor(np.array([0.0])),
paddle.to_tensor(np.array([0.0]))]])
def rz(self, theta, which_qubit):
r"""添加关于 z 轴的单量子比特旋转门。
......@@ -320,10 +573,10 @@ class UAnsatz:
which_qubit = 0
cir.rz(theta[0], which_qubit)
"""
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n(the number of qubit)"
self.__history.append(['u', [which_qubit], [paddle.to_tensor(np.array([0.0])),
paddle.to_tensor(np.array([0.0])),
theta]])
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n (the number of qubit)"
self.__history.append(['rz', [which_qubit], [paddle.to_tensor(np.array([0.0])),
paddle.to_tensor(np.array([0.0])),
theta]])
def cnot(self, control):
r"""添加一个 CNOT 门。
......@@ -350,7 +603,7 @@ class UAnsatz:
cir.cnot([0, 1])
"""
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)"
assert control[0] != control[1], "the control qubit is the same as the target qubit"
self.__history.append(['CNOT', control, None])
......@@ -362,7 +615,7 @@ class UAnsatz:
.. math::
\begin{align}
SWAP &=\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
SWAP = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
\end{align}
Args:
......@@ -378,7 +631,7 @@ class UAnsatz:
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)"
"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"
self.__history.append(['SWAP', control, None])
......@@ -409,7 +662,7 @@ class UAnsatz:
{'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])
def y(self, which_qubit):
......@@ -439,7 +692,7 @@ class UAnsatz:
{'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])
def z(self, which_qubit):
......@@ -469,7 +722,7 @@ class UAnsatz:
{'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])
def h(self, which_qubit):
......@@ -484,7 +737,7 @@ class UAnsatz:
Args:
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(['h', [which_qubit], None])
def s(self, which_qubit):
......@@ -499,8 +752,8 @@ class UAnsatz:
Args:
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)"
self.__history.append(['u', [which_qubit], [paddle.to_tensor(np.array([0.0])),
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n (the number of qubit)"
self.__history.append(['s', [which_qubit], [paddle.to_tensor(np.array([0.0])),
paddle.to_tensor(np.array([0.0])),
paddle.to_tensor(np.array([math.pi / 2]))]])
......@@ -516,8 +769,8 @@ class UAnsatz:
Args:
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)"
self.__history.append(['u', [which_qubit], [paddle.to_tensor(np.array([0.0])),
assert 0 <= which_qubit < self.n, "the qubit should >= 0 and < n (the number of qubit)"
self.__history.append(['t', [which_qubit], [paddle.to_tensor(np.array([0.0])),
paddle.to_tensor(np.array([0.0])),
paddle.to_tensor(np.array([math.pi / 4]))]])
......@@ -542,9 +795,151 @@ class UAnsatz:
lam (Tensor): 旋转角度 :math:`\lambda` 。
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], [theta, phi, lam]])
def rxx(self, theta, which_qubits):
r"""添加一个 RXX 门。
其矩阵形式为:
.. math::
\begin{align}
RXX(\theta) =
\begin{bmatrix}
\cos\frac{\theta}{2} & 0 & 0 & -i\sin\frac{\theta}{2} \\
0 & \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} & 0 \\
0 & -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} & 0 \\
-i\sin\frac{\theta}{2} & 0 & 0 & \cos\frac{\theta}{2}
\end{bmatrix}
\end{align}
Args:
theta (Tensor): 旋转角度
which_qubits (list): 作用在的两个量子比特的编号,其值都应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子电路的量子比特数
.. code-block:: python
import numpy as np
import paddle
from paddle_quantum.circuit import UAnsatz
num_qubits = 2
cir = UAnsatz(num_qubits)
cir.rxx(paddle.to_tensor(np.array([np.pi/2])), [0, 1])
"""
assert 0 <= which_qubits[0] < self.n and 0 <= which_qubits[1] < self.n, \
"the qubit should >= 0 and < n (the number of qubit)"
assert which_qubits[0] != which_qubits[1], "the indices of two qubits should be different"
self.__history.append(['RXX_gate', which_qubits, theta])
def ryy(self, theta, which_qubits):
r"""添加一个 RYY 门。
其矩阵形式为:
.. math::
\begin{align}
RYY(\theta) =
\begin{bmatrix}
\cos\frac{\theta}{2} & 0 & 0 & i\sin\frac{\theta}{2} \\
0 & \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} & 0 \\
0 & -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} & 0 \\
i\sin\frac{\theta}{2} & 0 & 0 & cos\frac{\theta}{2}
\end{bmatrix}
\end{align}
Args:
theta (Tensor): 旋转角度
which_qubits (list): 作用在的两个量子比特的编号,其值都应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子电路的量子比特数
.. code-block:: python
import numpy as np
import paddle
from paddle_quantum.circuit import UAnsatz
num_qubits = 2
cir = UAnsatz(num_qubits)
cir.ryy(paddle.to_tensor(np.array([np.pi/2])), [0, 1])
"""
assert 0 <= which_qubits[0] < self.n and 0 <= which_qubits[1] < self.n, \
"the qubit should >= 0 and < n (the number of qubit)"
assert which_qubits[0] != which_qubits[1], "the indices of two qubits should be different"
self.__history.append(['RYY_gate', which_qubits, theta])
def rzz(self, theta, which_qubits):
r"""添加一个 RZZ 门。
其矩阵形式为:
.. math::
\begin{align}
RZZ(\theta) =
\begin{bmatrix}
e^{-i\frac{\theta}{2}} & 0 & 0 & 0 \\
0 & e^{i\frac{\theta}{2}} & 0 & 0 \\
0 & 0 & e^{i\frac{\theta}{2}} & 0 \\
0 & 0 & 0 & e^{-i\frac{\theta}{2}}
\end{bmatrix}
\end{align}
Args:
theta (Tensor): 旋转角度
which_qubits (list): 作用在的两个量子比特的编号,其值都应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子电路的量子比特数
.. code-block:: python
import numpy as np
import paddle
from paddle_quantum.circuit import UAnsatz
num_qubits = 2
cir = UAnsatz(num_qubits)
cir.rzz(paddle.to_tensor(np.array([np.pi/2])), [0, 1])
"""
assert 0 <= which_qubits[0] < self.n and 0 <= which_qubits[1] < self.n, \
"the qubit should >= 0 and < n (the number of qubit)"
assert which_qubits[0] != which_qubits[1], "the indices of two qubits should be different"
self.__history.append(['RZZ_gate', which_qubits, theta])
def ms(self, which_qubits):
r"""添加一个 Mølmer-Sørensen (MS) 门,用于离子阱设备。
其矩阵形式为:
.. math::
\begin{align}
MS = RXX(-\frac{\pi}{2}) = \frac{1}{\sqrt{2}}
\begin{bmatrix}
1 & 0 & 0 & i \\
0 & 1 & i & 0 \\
0 & i & 1 & 0 \\
i & 0 & 0 & 1
\end{bmatrix}
\end{align}
Args:
which_qubits (list): 作用在的两个量子比特的编号,其值都应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子电路的量子比特数
Note:
参考文献 https://arxiv.org/abs/quant-ph/9810040
.. code-block:: python
import numpy as np
import paddle
from paddle_quantum.circuit import UAnsatz
num_qubits = 2
cir = UAnsatz(num_qubits)
cir.ms([0, 1])
"""
assert 0 <= which_qubits[0] < self.n and 0 <= which_qubits[1] < self.n, \
"the qubit should >= 0 and < n(the number of qubit)"
assert which_qubits[0] != which_qubits[1], "the indices of two qubits should be different"
self.__history.append(['MS_gate', which_qubits, paddle.to_tensor(-np.array([np.pi / 2]))])
def universal_2_qubit_gate(self, theta, which_qubits):
r"""添加 2-qubit 通用门,这个通用门需要 15 个参数。
......@@ -1237,7 +1632,7 @@ class UAnsatz:
gamma = 0.1
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0,1])
cir.cnot([0, 1])
cir.amplitude_damping(gamma, 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
......@@ -1284,7 +1679,7 @@ class UAnsatz:
p = 0.2
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0,1])
cir.cnot([0, 1])
cir.generalized_amplitude_damping(gamma, p, 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
......@@ -1330,7 +1725,7 @@ class UAnsatz:
p = 0.1
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0,1])
cir.cnot([0, 1])
cir.phase_damping(p, 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
......@@ -1373,7 +1768,7 @@ class UAnsatz:
p = 0.1
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0,1])
cir.cnot([0, 1])
cir.bit_flip(p, 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
......@@ -1416,7 +1811,7 @@ class UAnsatz:
p = 0.1
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0,1])
cir.cnot([0, 1])
cir.phase_flip(p, 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
......@@ -1459,7 +1854,7 @@ class UAnsatz:
p = 0.1
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0,1])
cir.cnot([0, 1])
cir.bit_phase_flip(p, 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
......@@ -1504,7 +1899,7 @@ class UAnsatz:
p = 0.1
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0,1])
cir.cnot([0, 1])
cir.depolarizing(p, 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
......@@ -1549,7 +1944,7 @@ class UAnsatz:
p_z = 0.3
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0,1])
cir.cnot([0, 1])
cir.pauli_channel(p_x, p_y, p_z, 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
......@@ -1576,6 +1971,117 @@ class UAnsatz:
return op_list
@apply_channel
def reset(self, p, q, which_qubit):
r"""添加重置信道。有 p 的概率将量子态重置为 :math:`|0\rangle` 并有 q 的概率重置为 :math:`|1\rangle`。
其 Kraus 算符为:
.. math::
E_0 = \begin{bmatrix} \sqrt{p} & 0 \\ 0 & 0 \end{bmatrix},
E_1 = \begin{bmatrix} 0 & \sqrt{p} \\ 0 & 0 \end{bmatrix},\\
E_2 = \begin{bmatrix} 0 & 0 \\ \sqrt{q} & 0 \end{bmatrix},
E_3 = \begin{bmatrix} 0 & 0 \\ 0 & \sqrt{q} \end{bmatrix},\\
E_4 = \sqrt{1-p-q} I.
Args:
p (float): 重置为 :math:`|0\rangle`的概率,其值应该在 :math:`[0, 1]` 区间内
q (float): 重置为 :math:`|1\rangle`的概率,其值应该在 :math:`[0, 1]` 区间内
which_qubit (int): 该信道作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子电路的量子比特数
Note:
两个输入的概率加起来需要小于等于 1。
代码示例:
.. code-block:: python
from paddle_quantum.circuit import UAnsatz
N = 2
p = 1
q = 0
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0, 1])
cir.reset(p, q, 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
::
[[0.5+0.j 0. +0.j 0. +0.j 0. +0.j]
[0. +0.j 0.5+0.j 0. +0.j 0. +0.j]
[0. +0.j 0. +0.j 0. +0.j 0. +0.j]
[0. +0.j 0. +0.j 0. +0.j 0. +0.j]]
"""
assert p + q <= 1, 'the sum of probabilities should be smaller than or equal to 1 '
e0 = paddle.to_tensor([[np.sqrt(p), 0], [0, 0]], dtype='complex128')
e1 = paddle.to_tensor([[0, np.sqrt(p)], [0, 0]], dtype='complex128')
e2 = paddle.to_tensor([[0, 0], [np.sqrt(q), 0]], dtype='complex128')
e3 = paddle.to_tensor([[0, 0], [0, np.sqrt(q)]], dtype='complex128')
e4 = paddle.to_tensor([[np.sqrt(1 - (p + q)), 0], [0, np.sqrt(1 - (p + q))]], dtype='complex128')
return [e0, e1, e2, e3, e4]
@apply_channel
def thermal_relaxation(self, t1, t2, time, which_qubit):
r"""添加热弛豫信道,模拟超导硬件上的 T1 和 T2 混合过程。
Args:
t1 (float): :math:`T_1` 过程的弛豫时间常数,单位是微秒
t2 (float): :math:`T_2` 过程的弛豫时间常数,单位是微秒
time (float): 弛豫过程中量子门的执行时间,单位是纳秒
which_qubit (int): 该信道作用在的 qubit 的编号,其值应该在 :math:`[0, n)` 范围内, :math:`n` 为该量子电路的量子比特数
Note:
时间常数必须满足 :math:`T_2 \le T_1`,参考文献 https://arxiv.org/abs/2101.02109
代码示例:
.. code-block:: python
from paddle_quantum.circuit import UAnsatz
N = 2
t1 = 30
t2 = 20
tg = 200
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0, 1])
cir.thermal_relaxation(t1, t2, tg, 0)
cir.thermal_relaxation(t1, t2, tg, 1)
final_state = cir.run_density_matrix()
print(final_state.numpy())
::
[[0.5 +0.j 0. +0.j 0. +0.j 0.4901+0.j]
[0. +0.j 0.0033+0.j 0. +0.j 0. +0.j]
[0. +0.j 0. +0.j 0.0033+0.j 0. +0.j]
[0.4901+0.j 0. +0.j 0. +0.j 0.4934+0.j]]
"""
assert 0 <= t2 <= t1, 'Relaxation time constants are not valid as 0 <= T2 <= T1!'
assert 0 <= time, 'Invalid gate time!'
# Change time scale
time = time / 1000
# Probability of resetting the state to |0>
p_reset = 1 - np.exp(-time / t1)
# Probability of phase flip
p_z = (1 - p_reset) * (1 - np.exp(-time / t2) * np.exp(time / t1)) / 2
# Probability of identity
p_i = 1- p_reset - p_z
e0 = paddle.to_tensor([[np.sqrt(p_i), 0], [0, np.sqrt(p_i)]], dtype='complex128')
e1 = paddle.to_tensor([[np.sqrt(p_z), 0], [0, -np.sqrt(p_z)]], dtype='complex128')
e2 = paddle.to_tensor([[np.sqrt(p_reset), 0], [0, 0]], dtype='complex128')
e3 = paddle.to_tensor([[0, np.sqrt(p_reset)], [0, 0]], dtype='complex128')
return [e0, e1, e2, e3]
@apply_channel
def customized_channel(self, ops, which_qubit):
r"""添加自定义的量子信道。
......@@ -1595,7 +2101,7 @@ class UAnsatz:
k2 = paddle.to_tensor([[0, 0], [0, 1]], dtype='complex128')
cir = UAnsatz(N)
cir.h(0)
cir.cnot([0,1])
cir.cnot([0, 1])
cir.customized_channel([k1, k2], 0)
final_state = cir.run_density_matrix()
print(final_state.numpy())
......@@ -1618,7 +2124,7 @@ class UAnsatz:
return ops
def __local_H_prob(cir, hamiltonian, shots=1024):
def _local_H_prob(cir, hamiltonian, shots=1024):
r"""
构造出 Pauli 测量电路并测量 ancilla,处理实验结果来得到 ``H`` (只有一项)期望值的实验测量值。
......@@ -1701,5 +2207,5 @@ def H_prob(cir, H, shots=1024):
"""
expval = 0
for term in H:
expval += term[0] * __local_H_prob(cir, term[1], shots=shots)
expval += term[0] * _local_H_prob(cir, term[1], shots=shots)
return expval
......@@ -121,14 +121,19 @@ def vec_expecval(H, vec):
def transfer_by_history(state, history):
r"""
It transforms the input state according to the history give.
It transforms the input state according to the history given.
Note:
这是内部函数,你并不需要直接调用到该函数。
"""
for history_ele in history:
if history_ele[0] != 'channel':
state = StateTransfer(state, history_ele[0], history_ele[1], params=history_ele[2])
if history_ele[0] in {'s', 't', 'ry', 'rz', 'rx'}:
state = StateTransfer(state, 'u', history_ele[1], params=history_ele[2])
elif history_ele[0] == 'MS_gate':
state = StateTransfer(state, 'RXX_gate', history_ele[1], params=history_ele[2])
else:
state = StateTransfer(state, history_ele[0], history_ele[1], params=history_ele[2])
return state
......
......@@ -18,10 +18,8 @@ import paddle
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import NKron, partial_trace, dagger
from paddle import matmul, trace, divide, kron, add, multiply
from paddle import sin, cos, concat, zeros, ones, real
from paddle_quantum.state import isotropic_state, bell_state
from paddle import sin, cos, real
from math import log2, sqrt
from numpy import pi as PI
class LoccStatus(object):
......@@ -30,8 +28,8 @@ class LoccStatus(object):
由于我们在 LOCC 中不仅关心量子态的解析形式,同时还关心得到它的概率,以及是经过怎样的测量而得到。因此该类包含三个成员变量:量子态 ``state`` 、得到这个态的概率 ``prob`` 和得到这个态的测量的测量结果是什么,即 ``measured_result`` 。
Attributes:
state (numpy.ndarray): 表示量子态的矩阵形式
prob (numpy.ndarray): 表示得到这个量子态的概率
state (paddle.Tensor): 表示量子态的矩阵形式
prob (paddle.Tensor): 表示得到这个量子态的概率
measured_result (str): 表示得到这个态的测量函数的测量结果
"""
......@@ -39,8 +37,8 @@ class LoccStatus(object):
r"""构造函数,用于实例化一个 ``LoccStatus`` 对象。
Args:
state (numpy.ndarray): 默认为 ``None`` ,该 ``LoccStatus`` 的量子态的矩阵形式
prob (numpy.ndarray): 默认为 ``None`` ,得到该量子态的概率
state (paddle.Tensor): 默认为 ``None`` ,该 ``LoccStatus`` 的量子态的矩阵形式
prob (paddle.Tensor): 默认为 ``None`` ,得到该量子态的概率
measured_result (str): 默认为 ``None`` ,表示得到这个态的测量函数的测量结果
"""
super(LoccStatus, self).__init__()
......@@ -499,7 +497,9 @@ class LoccAnsatz(UAnsatz):
def __add_complex_layer(self, theta, position):
r"""
Add a complex layer on the circuit. theta is a two dimensional tensor. position is the qubit range the layer needs to cover
Add a complex layer on the circuit.
Theta is a two dimensional tensor.
Position is the qubit range the layer needs to cover
Note:
这是内部函数,你并不需要直接调用到该函数。
......@@ -658,6 +658,7 @@ class LoccAnsatz(UAnsatz):
which_qubit = self.party[which_qubit]
super(LoccAnsatz, self).customized_channel(ops, which_qubit)
class LoccNet(paddle.nn.Layer):
r"""用于设计我们的 LOCC 下的 protocol,并进行验证或者训练。
"""
......@@ -734,18 +735,24 @@ class LoccNet(paddle.nn.Layer):
raise ValueError("can't recognize the input status")
assert max(qubits_list) <= n, "qubit index out of range"
qubit2idx = list(range(0, n))
idx2qubit = list(range(0, n))
origin_seq = list(range(0, n))
target_seq = [idx for idx in origin_seq if idx not in qubits_list]
target_seq = qubits_list + target_seq
swaped = [False] * n
swap_list = []
for idx in range(0, n):
if not swaped[idx]:
next_idx = idx
swaped[next_idx] = True
while not swaped[target_seq[next_idx]]:
swaped[target_seq[next_idx]] = True
swap_list.append((next_idx, target_seq[next_idx]))
next_idx = target_seq[next_idx]
cir = UAnsatz(n)
for i, ele in enumerate(qubits_list):
if qubit2idx[ele] != i:
# if qubit2idx[ele] is i, then swap([ele, i]) is identity
cir.swap([i, qubit2idx[ele]])
qubit2idx[idx2qubit[i]] = qubit2idx[ele]
idx2qubit[qubit2idx[ele]] = idx2qubit[i]
idx2qubit[i] = ele
qubit2idx[ele] = i
for a, b in swap_list:
cir.swap([a, b])
if isinstance(status, LoccStatus):
state = cir.run_density_matrix(status.state)
......@@ -798,25 +805,29 @@ class LoccNet(paddle.nn.Layer):
raise ValueError("can't recognize the input status")
assert max(qubits_list) <= n, "qubit index out of range"
qubit2idx = list(range(0, n))
idx2qubit = list(range(0, n))
swap_history = list()
origin_seq = list(range(0, n))
target_seq = [idx for idx in origin_seq if idx not in qubits_list]
target_seq = qubits_list + target_seq
swaped = [False] * n
swap_list = []
for idx in range(0, n):
if not swaped[idx]:
next_idx = idx
swaped[next_idx] = True
while not swaped[target_seq[next_idx]]:
swaped[target_seq[next_idx]] = True
swap_list.append((next_idx, target_seq[next_idx]))
next_idx = target_seq[next_idx]
cir0 = UAnsatz(n)
for i, ele in enumerate(qubits_list):
if qubit2idx[ele] != i: # if qubit2idx[ele] is i, then swap([ele, i]) is identity
swap_history.append((i, qubit2idx[ele]))
cir0.swap([i, qubit2idx[ele]])
qubit2idx[idx2qubit[i]] = qubit2idx[ele]
idx2qubit[qubit2idx[ele]] = idx2qubit[i]
idx2qubit[i] = ele
qubit2idx[ele] = i
for a, b in swap_list:
cir0.swap([a, b])
cir1 = UAnsatz(n)
swap_cnt = len(swap_history)
for idx in range(0, swap_cnt):
a, b = swap_history[swap_cnt - 1 - idx]
cir1.swap([b, a])
swap_list.reverse()
for a, b in swap_list:
cir1.swap([a, b])
if isinstance(status, LoccStatus):
_state = cir0.run_density_matrix(status.state)
......
......@@ -200,7 +200,7 @@ def cx_gate_matrix():
def swap_gate_matrix():
"""
Control Not
Swap gate
:return:
"""
return np.array([[1, 0, 0, 0],
......@@ -209,6 +209,71 @@ def swap_gate_matrix():
[0, 0, 0, 1]], dtype=complex).reshape(2, 2, 2, 2)
def rxx_gate_matrix(params):
"""
RXX gate
:return:
"""
theta = params
re_a = paddle.cos(theta / 2)
re_b = paddle.zeros([1], 'float64')
im_a = paddle.sin(theta / 2)
im_b = paddle.zeros([1], 'float64')
re = paddle.reshape(paddle.concat([re_a, re_b, re_b, re_b,
re_b, re_a, re_b, re_b,
re_b, re_b, re_a, re_b,
re_b, re_b, re_b, re_a]), [4, 4])
im = paddle.reshape(paddle.concat([im_b, im_b, im_b, im_a,
im_b, im_b, im_a, im_b,
im_b, im_a, im_b, im_b,
im_a, im_b, im_b, im_b]), [4, 4])
return re - im * paddle.to_tensor([1j], 'complex128')
def ryy_gate_matrix(params):
"""
RYY gate
:return:
"""
theta = params
re_a = paddle.cos(theta / 2)
re_b = paddle.zeros([1], 'float64')
im_a = paddle.sin(theta / 2)
im_b = paddle.zeros([1], 'float64')
re = paddle.reshape(paddle.concat([re_a, re_b, re_b, re_b,
re_b, re_a, re_b, re_b,
re_b, re_b, re_a, re_b,
re_b, re_b, re_b, re_a]), [4, 4])
im = paddle.reshape(paddle.concat([im_b, im_b, im_b, im_a,
im_b, im_b, -im_a, im_b,
im_b, -im_a, im_b, im_b,
im_a, im_b, im_b, im_b]), [4, 4])
return re + im * paddle.to_tensor([1j], 'complex128')
def rzz_gate_matrix(params):
"""
RZZ gate
:return:
"""
theta = params
re_a = paddle.cos(theta / 2)
re_b = paddle.zeros([1], 'float64')
im_a = paddle.sin(theta / 2)
im_b = paddle.zeros([1], 'float64')
re = paddle.reshape(paddle.concat([re_a, re_b, re_b, re_b,
re_b, re_a, re_b, re_b,
re_b, re_b, re_a, re_b,
re_b, re_b, re_b, re_a]), [4, 4])
im = paddle.reshape(paddle.concat([-im_a, im_b, im_b, im_b,
im_b, im_a, im_b, im_b,
im_b, im_b, im_a, im_b,
im_b, im_b, im_b, -im_a]), [4, 4])
return re + im * paddle.to_tensor([1j], 'complex128')
# PaddleE
def normalize_axis(axis, ndim):
if axis < 0:
......@@ -410,6 +475,15 @@ def StateTransfer(state, gate_name, bits, params=None):
elif gate_name == 'u':
# print('----------', gate_name, bits, '----------')
gate_matrix = u_gate_matrix(params)
elif gate_name == 'RXX_gate':
# print('----------', gate_name, bits, '----------')
gate_matrix = rxx_gate_matrix(params)
elif gate_name == 'RYY_gate':
# print('----------', gate_name, bits, '----------')
gate_matrix = ryy_gate_matrix(params)
elif gate_name == 'RZZ_gate':
# print('----------', gate_name, bits, '----------')
gate_matrix = rzz_gate_matrix(params)
else:
raise Exception("Gate name error")
......
......@@ -13,31 +13,17 @@
# limitations under the License.
from functools import reduce
from math import log2
import numpy as np
from numpy import absolute, log
from numpy import diag, dot, identity
from numpy import kron as np_kron
from numpy import trace as np_trace
from numpy import matmul as np_matmul
from numpy import random as np_random
from numpy import linalg, sqrt
from numpy import sum as np_sum
from numpy import transpose as np_transpose
from numpy import zeros as np_zeros
import paddle
from paddle import add, to_tensor
from paddle import kron as pp_kron
from paddle import kron as kron
from paddle import matmul
from paddle import transpose as pp_transpose
from paddle import concat, cos, ones, reshape, sin
from paddle import zeros as pp_zeros
from paddle import transpose
from paddle import concat, ones
from paddle import zeros
from scipy.linalg import logm, sqrtm
import paddle
__all__ = [
"partial_trace",
"state_fidelity",
......@@ -73,32 +59,76 @@ def partial_trace(rho_AB, dim1, dim2, A_or_B):
if A_or_B == 2:
dim1, dim2 = dim2, dim1
idty_np = identity(dim2).astype("complex128")
idty_np = np.identity(dim2).astype("complex128")
idty_B = to_tensor(idty_np)
zero_np = np_zeros([dim2, dim2], "complex128")
zero_np = np.zeros([dim2, dim2], "complex128")
res = to_tensor(zero_np)
for dim_j in range(dim1):
row_top = pp_zeros([1, dim_j], dtype="float64")
row_top = zeros([1, dim_j], dtype="float64")
row_mid = ones([1, 1], dtype="float64")
row_bot = pp_zeros([1, dim1 - dim_j - 1], dtype="float64")
row_bot = zeros([1, dim1 - dim_j - 1], dtype="float64")
bra_j = concat([row_top, row_mid, row_bot], axis=1)
bra_j = paddle.cast(bra_j, 'complex128')
if A_or_B == 1:
row_tmp = pp_kron(bra_j, idty_B)
row_tmp = kron(bra_j, idty_B)
row_tmp_conj = paddle.conj(row_tmp)
res = add(res, matmul(matmul(row_tmp, rho_AB), pp_transpose(row_tmp_conj, perm=[1, 0]), ), )
res = add(res, matmul(matmul(row_tmp, rho_AB), transpose(row_tmp_conj, perm=[1, 0]), ), )
if A_or_B == 2:
row_tmp = pp_kron(idty_B, bra_j)
row_tmp = kron(idty_B, bra_j)
row_tmp_conj = paddle.conj(row_tmp)
res = add(res, matmul(matmul(row_tmp, rho_AB), pp_transpose(row_tmp_conj, perm=[1, 0]), ), )
res = add(res, matmul(matmul(row_tmp, rho_AB), transpose(row_tmp_conj, perm=[1, 0]), ), )
return res
def partial_trace_discontiguous(rho, preserve_qubits=None):
r"""计算量子态的偏迹,可选取任意子系统。
Args:
rho (Tensor): 输入的量子态
preserve_qubits (list): 要保留的量子比特,默认为 None,表示全保留
"""
if preserve_qubits is None:
return rho
else:
n = int(log2(rho.size) // 2)
num_preserve = len(preserve_qubits)
shape = paddle.ones((n + 1,))
shape = 2 * shape
shape[n] = 2**n
shape = paddle.cast(shape, "int32")
identity = paddle.eye(2 ** n)
identity = paddle.reshape(identity, shape=shape)
discard = list()
for idx in range(0, n):
if idx not in preserve_qubits:
discard.append(idx)
addition = [n]
preserve_qubits.sort()
preserve_qubits = paddle.to_tensor(preserve_qubits)
discard = paddle.to_tensor(discard)
addition = paddle.to_tensor(addition)
permute = paddle.concat([discard, preserve_qubits, addition])
identity = paddle.transpose(identity, perm=permute)
identity = paddle.reshape(identity, (2**n, 2**n))
result = np.zeros((2 ** num_preserve, 2 ** num_preserve), dtype="complex64")
result = paddle.to_tensor(result)
for i in range(0, 2 ** num_preserve):
bra = identity[i * 2 ** num_preserve:(i + 1) * 2 ** num_preserve, :]
result = result + matmul(matmul(bra, rho), transpose(bra, perm=[1, 0]))
return result
def state_fidelity(rho, sigma):
r"""计算两个量子态的保真度。
......@@ -136,7 +166,7 @@ def gate_fidelity(U, V):
"""
assert U.shape == V.shape, 'The shape of two unitary matrices are different'
dim = U.shape[0]
fidelity = absolute(np_trace(np_matmul(U, V.conj().T)))/dim
fidelity = np.absolute(np.trace(np.matmul(U, V.conj().T)))/dim
return fidelity
......@@ -154,7 +184,7 @@ def purity(rho):
Returns:
float: 输入的量子态的纯度
"""
gamma = np_trace(np_matmul(rho, rho))
gamma = np.trace(np.matmul(rho, rho))
return gamma.real
......@@ -172,8 +202,8 @@ def von_neumann_entropy(rho):
Returns:
float: 输入的量子态的冯诺依曼熵
"""
rho_eigenvalue, _ = linalg.eig(rho)
entropy = -np_sum(rho_eigenvalue*log(rho_eigenvalue))
rho_eigenvalue, _ = np.linalg.eig(rho)
entropy = -np.sum(rho_eigenvalue*np.log(rho_eigenvalue))
return entropy.real
......@@ -219,7 +249,7 @@ def NKron(matrix_A, matrix_B, *args):
``result`` 应为 :math:`A \otimes B \otimes C`
"""
return reduce(lambda result, index: np_kron(result, index), args, np_kron(matrix_A, matrix_B), )
return reduce(lambda result, index: np.kron(result, index), args, np.kron(matrix_A, matrix_B), )
def dagger(matrix):
......@@ -246,7 +276,7 @@ def dagger(matrix):
[2.-2.j 4.-4.j]]
"""
matrix_conj = paddle.conj(matrix)
matrix_dagger = pp_transpose(matrix_conj, perm=[1, 0])
matrix_dagger = transpose(matrix_conj, perm=[1, 0])
return matrix_dagger
......@@ -266,11 +296,11 @@ def random_pauli_str_generator(n, terms=3):
list: 随机生成的可观测量的列表形式
"""
pauli_str = []
for sublen in np_random.randint(1, high=n+1, size=terms):
for sublen in np.random.randint(1, high=n+1, size=terms):
# Tips: -1 <= coeff < 1
coeff = np_random.rand()*2-1
ops = np_random.choice(['x', 'y', 'z'], size=sublen)
pos = np_random.choice(range(n), size=sublen, replace=False)
coeff = np.random.rand()*2-1
ops = np.random.choice(['x', 'y', 'z'], size=sublen)
pos = np.random.choice(range(n), size=sublen, replace=False)
op_list = [ops[i]+str(pos[i]) for i in range(sublen)]
pauli_str.append([coeff, ','.join(op_list)])
return pauli_str
......
......@@ -23,7 +23,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
setuptools.setup(
name='paddle-quantum',
version='2.0.1',
version='2.1.0',
author='Institute for Quantum Computing, Baidu INC.',
author_email='quantum@baidu.com',
description='Paddle Quantum is a quantum machine learning (QML) toolkit developed based on Baidu PaddlePaddle.',
......@@ -34,7 +34,7 @@ setuptools.setup(
'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'],
install_requires=['paddlepaddle>=2.0.1', 'scipy', 'networkx', 'matplotlib', 'interval', 'tqdm'],
install_requires=['paddlepaddle>=2.0.1', 'scipy', 'networkx>=2.5', 'matplotlib', 'interval', 'tqdm'],
python_requires='>=3.6, <4',
classifiers=[
'Programming Language :: Python :: 3',
......
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 量子神经网络的贫瘠高原效应\n",
"\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 概览\n",
"\n",
"在经典神经网络的训练中,基于梯度的优化方法不仅仅会遇到局部最小值的问题,同时还要面对鞍点等附近梯度近似于零的几何结构。相对应的,在量子神经网络中也存在着一种**贫瘠高原效应**(Barren plateaus)。这个奇特的现象首先是由 McClean et al. 在 2018 年发现 [[arXiv:1803.11173]](https://arxiv.org/abs/1803.11173)。简单来说,就是当你选取的随机电路结构满足一定复杂程度时优化曲面(Optimization landscape)会变得很平坦,从而导致基于梯度下降的优化方法很难找到全局最小值。对于大多数的变分量子算法(VQE等等),这个现象意味着当量子比特数量越来越多时,选取随机结构的电路有可能效果并不好。这会让你设计的损失函数所对应的优化曲面变成一个巨大的高原,让从而导致量子神经网络的训练愈加困难。你随机找到的初始值很难逃离这个高原,梯度下降收敛速度会很缓慢。\n",
"\n",
"![BP-fig-barren](./figures/BP-fig-barren-cn.png)\n",
"\n",
"图片由 [Gradient Descent Viz](https://github.com/lilipads/gradient_descent_viz) 生成\n",
"\n",
"本教程主要讨论如何在量桨(PaddleQuantum)平台上展示贫瘠高原这一现象。其中并不涉及任何算法创新,但能提升读者对于量子神经网络训练中梯度问题的认识。首先我们先引入必要的 library和 package:\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:20:39.463025Z",
"start_time": "2021-03-02T12:20:36.336398Z"
}
},
"outputs": [],
"source": [
"import time\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt \n",
"import paddle\n",
"from paddle import matmul as matmul\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import dagger\n",
"from paddle_quantum.state import density_op"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 随机的网络结构\n",
"\n",
"这里我们按照原作者 McClean (2018)论文中提及的类似方法搭建如下随机电路(目前我们不支持内置的 control-Z 门,方便起见用 CNOT 替代):\n",
"\n",
"![BP-fig-Barren_circuit](./figures/BP-fig-Barren_circuit.png)\n",
"\n",
"首先作用在所有量子比特上绕布洛赫球的 Y-轴旋转 $\\pi/4$。\n",
"\n",
"其余的结构加起来构成一个模块(Block), 每个模块共分为两层:\n",
"\n",
"- 第一层搭建随机的旋转门, 其中 $R_{\\ell,n} \\in \\{R_x, R_y, R_z\\}$。下标 $\\ell$ 表示处于第 $\\ell$ 个重复的模块, 上图中 $\\ell =1$。第二个下标 $n$ 表示作用在第几个量子比特上。\n",
"- 第二层由 CNOT 门组成,作用在每两个相邻的量子比特上。\n",
"\n",
"在量桨中, 我们可以这么搭建。"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:20:39.972053Z",
"start_time": "2021-03-02T12:20:39.962259Z"
}
},
"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"
]
}
],
"source": [
"def rand_circuit(theta, target, num_qubits):\n",
" # 我们需要将 Numpy array 转换成 Paddle 中的 Tensor\n",
" const = paddle.to_tensor(np.array([np.pi/4]))\n",
" \n",
" # 初始化量子电路\n",
" cir = UAnsatz(num_qubits)\n",
" \n",
" # ============== 第一层 ==============\n",
" # 固定角度的 Ry 旋转门\n",
" for i in range(num_qubits):\n",
" cir.ry(const, i)\n",
"\n",
" # ============== 第二层 ==============\n",
" # target是一个随机的数组,用来帮助我们抽取随机的单比特门 \n",
" for i in range(num_qubits):\n",
" if target[i] == 0:\n",
" cir.rz(theta[i], i)\n",
" elif target[i] == 1:\n",
" cir.ry(theta[i], i)\n",
" else:\n",
" cir.rx(theta[i], i)\n",
" \n",
" # ============== 第三层 ==============\n",
" # 搭建两两相邻的 CNOT 门\n",
" for i in range(num_qubits - 1):\n",
" cir.cnot([i, i + 1])\n",
" \n",
" return cir.U"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 损失函数与优化曲面 \n",
"\n",
"当我们确定了电路的结构之后,我们还需要定义一个损失函数(Loss function)来确定优化曲面(Optimization landscape)。按照原作者 McClean (2018)论文中提及的,我们采用 VQE算法中常用的损失函数:\n",
"\n",
"$$\n",
"\\mathcal{L}(\\boldsymbol{\\theta})= \\langle0| U^{\\dagger}(\\boldsymbol{\\theta})H U(\\boldsymbol{\\theta}) |0\\rangle,\n",
"\\tag{1}\n",
"$$\n",
"\n",
"其中的酉矩阵 $U(\\boldsymbol{\\theta})$ 就是我们上一部分搭建的带有随机结构的量子神经网络。对于其中的哈密顿量 $H$ 我们不妨先取最简单的形式 $H = |00\\cdots 0\\rangle\\langle00\\cdots 0|$。设定好这些后,我们就可以从最简单的两个量子比特的情形开始采样了 -- 生成 300 组随机网络结构和不同的随机初始参数 $\\{\\theta_{\\ell,n}^{(i)}\\}_{i=1}^{300}$。每次计算梯度都是按照 VQE 的解析梯度公式计算关于 **第一个参数 $\\theta_{1,1}$** 的偏导数。然后统计得到的这 300 个梯度的平均值和方差。其中解析梯度的公式为:\n",
"\n",
"$$\n",
"\\partial \\theta_{j} \n",
"\\equiv \\frac{\\partial \\mathcal{L}}{\\partial \\theta_j}\n",
"= \\frac{1}{2} \\big[\\mathcal{L}(\\theta_j + \\frac{\\pi}{2}) - \\mathcal{L}(\\theta_j - \\frac{\\pi}{2})\\big].\n",
"\\tag{2}\n",
"$$\n",
"\n",
"具体推导请参见:[arXiv:1803.00745](https://arxiv.org/abs/1803.00745)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:20:52.236108Z",
"start_time": "2021-03-02T12:20:40.850822Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"主程序段总共运行了 35.180830001831055 秒\n",
"采样 300 个随机网络关于第一个参数梯度的均值是: 0.005925709445960606\n",
"采样 300 个随机网络关于第一个参数梯度的方差是: 0.028249053148446363\n"
]
}
],
"source": [
"# 超参数设置\n",
"np.random.seed(42) # 固定 Numpy 的随机种子\n",
"N = 2 # 设置量子比特数量 \n",
"samples = 300 # 设定采样随机网络结构的数量\n",
"THETA_SIZE = N # 设置参数 theta 的大小\n",
"ITR = 1 # 设置迭代次数\n",
"LR = 0.2 # 设定学习速率\n",
"SEED = 1 # 固定优化器中随机初始化的种子\n",
"\n",
"# 初始化梯度数值的寄存器\n",
"grad_info = []\n",
"\n",
"paddle.seed(SEED)\n",
"\n",
"class manual_gradient(paddle.nn.Layer):\n",
" \n",
" # 初始化一个可学习参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值\n",
" def __init__(self, shape, param_attr=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),dtype='float64'):\n",
" super(manual_gradient, self).__init__()\n",
" \n",
" # 将 Numpy array 转换成 Paddle 中的 Tensor\n",
" self.H = paddle.to_tensor(density_op(N))\n",
" \n",
" # 定义损失函数和前向传播机制 \n",
" def forward(self):\n",
" \n",
" # 初始化三个 theta 参数列表\n",
" theta_np = np.random.uniform(low=0., high= 2 * np.pi, size=(THETA_SIZE))\n",
" theta_plus_np = np.copy(theta_np) \n",
" theta_minus_np = np.copy(theta_np) \n",
" \n",
" # 修改用以计算解析梯度\n",
" theta_plus_np[0] += np.pi/2\n",
" theta_minus_np[0] -= np.pi/2\n",
" \n",
" # 将 Numpy array 转换成 Paddle 中的 Tensor\n",
" theta = paddle.to_tensor(theta_np)\n",
" theta_plus = paddle.to_tensor(theta_plus_np)\n",
" theta_minus = paddle.to_tensor(theta_minus_np)\n",
" \n",
" # 生成随机目标,在 rand_circuit 中随机选取电路门\n",
" target = np.random.choice(3, N) \n",
" \n",
" U = rand_circuit(theta, target, N)\n",
" U_dagger = dagger(U) \n",
" U_plus = rand_circuit(theta_plus, target, N)\n",
" U_plus_dagger = dagger(U_plus) \n",
" U_minus = rand_circuit(theta_minus, target, N)\n",
" U_minus_dagger = dagger(U_minus) \n",
"\n",
" # 计算解析梯度\n",
" grad = (paddle.real(matmul(matmul(U_plus_dagger, self.H), U_plus))[0][0] \n",
" - paddle.real(matmul(matmul(U_minus_dagger, self.H), U_minus))[0][0])/2 \n",
" \n",
" return grad\n",
"\n",
"# 定义主程序段\n",
"def main():\n",
" \n",
" # 设置QNN的维度\n",
" sampling = manual_gradient(shape=[THETA_SIZE])\n",
"\n",
" # 采样获得梯度信息\n",
" grad = sampling() \n",
" \n",
" return grad.numpy()\n",
"\n",
"\n",
"# 记录运行时间\n",
"time_start = time.time()\n",
"\n",
"# 开始采样\n",
"for i in range(samples):\n",
" if __name__ == '__main__':\n",
" grad = main()\n",
" grad_info.append(grad)\n",
"\n",
"time_span = time.time() - time_start \n",
"print('主程序段总共运行了', time_span, '秒')\n",
"print(\"采样\", samples, \"个随机网络关于第一个参数梯度的均值是:\", np.mean(grad_info))\n",
"print(\"采样\", samples, \"个随机网络关于第一个参数梯度的方差是:\", np.var(grad_info))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 优化曲面的可视化\n",
"\n",
"接下来我们试着利用 Matplotlib来可视化这个优化曲面(Optimization landscape)。在**两个量子比特**的情况下,我们只有两个参数 $\\theta_1$ 和 $\\theta_2$, 并且第二层的随机电路电路总共有9种情况。这个很容易画出来:\n",
"\n",
"![BP-fig-landscape2](./figures/BP-fig-landscape2.png)\n",
"\n",
"可以看到的是最后一张图中 $R_z$-$R_z$ 结构所展示出的平原结构是我们非常不想见到的。在这种情况下,我们不能收敛到理论最小值。如果你想自己试着画一些优化曲面,不妨参见以下代码:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:21:49.972769Z",
"start_time": "2021-03-02T12:21:45.792119Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 960x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"主程序段总共运行了 12.931725025177002 秒\n"
]
}
],
"source": [
"# 引入必要的 package\n",
"from matplotlib import cm\n",
"from mpl_toolkits.mplot3d import Axes3D\n",
"from matplotlib.ticker import LinearLocator, FormatStrFormatter\n",
"\n",
"time_start = time.time()\n",
"N = 2\n",
"\n",
"# 设置图像比例 竖:横 = 0.3 \n",
"fig = plt.figure(figsize=plt.figaspect(0.3))\n",
"\n",
"# 生成 x, y 轴上的点\n",
"X = np.linspace(0, 2*np.pi, 80)\n",
"Y = np.linspace(0, 2*np.pi, 80)\n",
"\n",
"# 生成 2D 网格 (mesh)\n",
"xx, yy = np.meshgrid(X, Y)\n",
"\n",
"\n",
"# 定义必要的逻辑门\n",
"def rx(theta):\n",
" mat = np.array([[np.cos(theta/2), -1j*np.sin(theta/2)],\n",
" [-1j*np.sin(theta/2), np.cos(theta/2)]])\n",
" return mat\n",
"\n",
"def ry(theta):\n",
" mat = np.array([[np.cos(theta/2), -1*np.sin(theta/2)],\n",
" [np.sin(theta/2), np.cos(theta/2)]])\n",
" return mat\n",
"\n",
"def rz(theta):\n",
" mat = np.array([[np.exp(-1j*theta/2), 0],\n",
" [0, np.exp(1j*theta/2)]])\n",
" return mat\n",
"\n",
"def CNOT():\n",
" mat = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]])\n",
" return mat\n",
"\n",
"# ============= 第一张图 =============\n",
"# 我们可视化第二层是 kron(Ry, Ry) 的情况\n",
"ax = fig.add_subplot(1, 2, 1, projection='3d')\n",
"\n",
"# 向前传播计算损失函数:\n",
"def cost_yy(para):\n",
" L1 = np.kron(ry(np.pi/4), ry(np.pi/4))\n",
" L2 = np.kron(ry(para[0]), ry(para[1]))\n",
" U = np.matmul(np.matmul(L1, L2), CNOT())\n",
" H = np.zeros((2 ** N, 2 ** N))\n",
" H[0, 0] = 1\n",
" val = (U.conj().T @ H@ U).real[0][0]\n",
" return val\n",
"\n",
"# 画出图像\n",
"Z = np.array([[cost_yy([x, y]) for x in X] for y in Y]).reshape(len(Y), len(X))\n",
"surf = ax.plot_surface(xx, yy, Z, cmap='plasma')\n",
"#cset = ax.contourf(xx, yy, Z, zdir='z', offset=np.min(Z), cmap='viridis')\n",
"ax.set_xlabel(r\"$\\theta_1$\")\n",
"ax.set_ylabel(r\"$\\theta_2$\")\n",
"ax.set_title(\"Optimization Landscape for Ry-Ry Layer\")\n",
"#fig.colorbar(surf, shrink=0.5, aspect=5)\n",
"\n",
"# ============= 第二张图 =============\n",
"# 我们可视化第二层是 kron(Rx, Rz) 的情况\n",
"ax = fig.add_subplot(1, 2, 2, projection='3d')\n",
"\n",
"\n",
"def cost_xz(para):\n",
" L1 = np.kron(ry(np.pi/4), ry(np.pi/4))\n",
" L2 = np.kron(rx(para[0]), rz(para[1]))\n",
" U = np.matmul(np.matmul(L1, L2), CNOT())\n",
" H = np.zeros((2 ** N, 2 ** N))\n",
" H[0, 0] = 1\n",
" val = (U.conj().T @ H@ U).real[0][0]\n",
" return val\n",
"\n",
"Z = np.array([[cost_xz([x, y]) for x in X] for y in Y]).reshape(len(Y), len(X))\n",
"surf = ax.plot_surface(xx, yy, Z, cmap='viridis')\n",
"#cset = ax.contourf(xx, yy, Z, zdir='z', offset=np.min(Z), cmap='viridis')\n",
"ax.set_xlabel(r\"$\\theta_1$\")\n",
"ax.set_ylabel(r\"$\\theta_2$\")\n",
"ax.set_title(\"Optimization Landscape for Rx-Rz Layer\")\n",
"\n",
"\n",
"plt.show()\n",
"\n",
"time_span = time.time() - time_start \n",
"print('主程序段总共运行了', time_span, '秒')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 更多的量子比特\n",
"\n",
"接着我们再看看不断的增加量子比特的数量,会对我们的梯度带来什么影响。"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:24:12.650054Z",
"start_time": "2021-03-02T12:22:06.472689Z"
}
},
"outputs": [],
"source": [
"# 超参数设置\n",
"selected_qubit = [2, 4, 6, 8]\n",
"samples = 300\n",
"grad_val = []\n",
"means, variances = [], []\n",
"\n",
"\n",
"# 记录运算时长\n",
"time_start = time.time()\n",
"\n",
"# 不断增加量子比特数量\n",
"for N in selected_qubit:\n",
" grad_info = []\n",
" THETA_SIZE = N\n",
" for i in range(samples):\n",
" class manual_gradient(paddle.nn.Layer):\n",
" # 初始化一个长度为 THETA_SIZE 的可学习参数列表\n",
" def __init__(self, shape, param_attr=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),dtype='float64'):\n",
" super(manual_gradient, self).__init__()\n",
"\n",
" # 转换成 Paddle 中的 Tensor\n",
" self.H = paddle.to_tensor(density_op(N))\n",
"\n",
" # 定义损失函数和前向传播机制 \n",
" def forward(self):\n",
"\n",
" # 初始化三个 theta 参数列表\n",
" theta_np = np.random.uniform(low=0., high= 2 * np.pi, size=(THETA_SIZE))\n",
" theta_plus_np = np.copy(theta_np) \n",
" theta_minus_np = np.copy(theta_np) \n",
"\n",
" # 修改用以计算解析梯度\n",
" theta_plus_np[0] += np.pi/2\n",
" theta_minus_np[0] -= np.pi/2\n",
"\n",
" # 转换成 Paddle 中的 Tensor\n",
" theta = paddle.to_tensor(theta_np)\n",
" theta_plus = paddle.to_tensor(theta_plus_np)\n",
" theta_minus = paddle.to_tensor(theta_minus_np)\n",
"\n",
" # 生成随机目标,在 rand_circuit 中随机选取电路门\n",
" target = np.random.choice(3, N) \n",
" \n",
" U = rand_circuit(theta, target, N)\n",
" U_dagger = dagger(U) \n",
" U_plus = rand_circuit(theta_plus, target, N)\n",
" U_plus_dagger = dagger(U_plus) \n",
" U_minus = rand_circuit(theta_minus, target, N)\n",
" U_minus_dagger = dagger(U_minus) \n",
"\n",
" \n",
" # 计算解析梯度\n",
" grad = (paddle.real(matmul(matmul(U_plus_dagger, self.H), U_plus))[0][0] \n",
" - paddle.real(matmul(matmul(U_minus_dagger, self.H), U_minus))[0][0])/2\n",
" \n",
" return grad \n",
" \n",
" \n",
" # 定义主程序段 \n",
" def main():\n",
" \n",
" # 设置QNN的维度\n",
" sampling = manual_gradient(shape=[THETA_SIZE])\n",
"\n",
" # 采样获得梯度信息\n",
" grad = sampling()\n",
"\n",
" return grad.numpy()\n",
" \n",
" if __name__ == '__main__':\n",
" grad = main()\n",
" grad_info.append(grad)\n",
" \n",
" # 记录采样信息\n",
" grad_val.append(grad_info) \n",
" means.append(np.mean(grad_info))\n",
" variances.append(np.var(grad_info))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:24:30.342035Z",
"start_time": "2021-03-02T12:24:29.346060Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"我们接着画出这个采样出来的梯度的统计结果:\n"
]
},
{
"data": {
"image/png": "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IiIJlpeXx7Rp0xg3bhxt27ZlxIgR3FeSFEXef/99hgwZQtu2bcnJyeHkk0/mtddeA0KNx4gRIwA45ZRTeOONNygqKuKtt97i+OOPp3///vzmN79hwYIFCY373XffpUmTJuy8884AbNy4kXnz5rHXXnvx4Ycfsueee/L73/++dN/cuXMpLCxkwoQJnHnmmaxcuZK77rqLww47jPz8/ITGFkt9YkRERERk21dYWPm+Jk2q3t+mTdX7K5Gdnc2QIUMYMmQI/fr14/777+e0006r8XkgDElcXFxMy5YtSzvcV2bYsGEsWrSI3Xbbjbvvvpvvv/+ejRs3kpOTw7x58+jYsWOl7504cWJpLQxA69atadKkCcceeywAxx9/PPfeey8QanUGDx5MgwYN6NatG7169WLu3Lm8/fbbvP7669x1110UFRWxfv168vLyuOGGG7bqs1dENTEiIiK1pD4xIlLe7NmzmTt3bun69OnT6dKlS5ljdt99d1599VWWLl3Kpk2bmDBhAj/96U+B0CTrscceA+Dhhx9mn332oXnz5nTr1o1HH30UCP1d/vvf/25x7SlTpjB9+nTuuecezIz99tuv9Fz3338/Rx99dIUxFxcXM2nSpDL9YcyMI488ksIoiZs6dSp9+vQBYPjw4aXbly5dypw5c+jevTsPPfQQ33zzDV999RVjxozhl7/8ZUITGFASIyIiUmvqEyMi5RUVFXHqqafSp08fdtllFz799FNGjx5d5pj27dtzww03sP/++7PrrrsyaNCg0gSjadOmvPfee+y88868/PLLXHHFFUAYCvnee+9l1113pW/fvjz99NPVxnLVVVcxduxYevTowbJlyzj99NMBmDx5cul5AV577TU6depE9+7dy7z/xhtvZPTo0eyyyy48+OCD3HLLLUCo8WndujV9+vRh//335+abb6Z169Zb/Z3VhJqTiYiIiIgk2KBBg3jrrbcq3FcY0zTtxBNPLNN8K9bYsWO32NatW7fSDvTx6tatG++9994W24866iiOOuqo0vUhQ4bwzjvvbHFcly5dSvvqxDIzxo4dW2GcJU477bStbkJXFdXEiIiIiIhIRlESIyIiIiKSZtTHrmpKYkRERERkm+TuqQ5BKlHb342SGBERkVrS6GQi6Sc3N5dly5YpkUlD7s6yZcvIzc3d6nOoY7+IiEgtufszwDMFBQVn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ecDvgGuTH6qIiIiISAqZwZFHwiefwC23wFtvwccfpzqqOpUuk11u7+4LouWFwPYVHNMR+DZmfV60DeAa4BZgTdIiFBERERFJJw0bwu9+B6edBq2iBkp//SsUF8M550CDBikNL5nqLIkxs/8AO1Sw6/LYFXd3M/ManLc/sKO7X2BmXeM4fiQwEqBt27YUFhbGe6mUKSoqUpwJlimxKs7EypQ4IbNiFRGRFNtuu/DTHV55BZ58Ev72Nxg7Fg49NLWxJUmdJTHufmBl+8xskZm1d/cFZtYeWFzBYfOBITHr+UAhsCewm5l9Rfg87cys0N2HUAF3HweMAygoKPAhQyo8LK0UFhaiOBMrU2JVnImVKXFCZsUqYbJL4MgOHTqkOhQRqc/M4PHH4bnnQg3N4YfDsGE0PumkVEeWcOnSJ2YyUDLa2KnA0xUcMwU42MxaRR36DwamuPvf3L2Du3cF9gHmVJbAiIiIJIMmuxSRtGEGRxwR+suMHQvvvUfOmm2vx0W6JDE3AAeZ2VzgwGgdM9vNzO4BcPflhL4v70evq6NtIiIiIiISq2FDuOAC+PZbVvfunepoEi4tOva7+zJgaAXbPwDOiFkfD4yv4jxfATsnIUQRERERkczTtGmqI0iKdKmJERERERERiYuSGBERERERyShKYkREREREJKMoiRERERERkYyiJEZERERERDKKkhgREREREckoSmJERERERCSjKIkREREREZGMoiRGREREREQyipIYERGRWjKzI81sXFFRUapDERGpF5TEiIiI1JK7P+PuI/Py8lIdiohIvaAkRkREREREMoqSGBERERERyShKYkREREREJKMoiRERERERkYyiJEZERERERDKKkhgREREREckoSmJERERERCSjKIkREREREZGMoiRGREREREQyipIYERERERHJKEpiREREREQkoyiJERERERGRjKIkRkREREREMoqSGBERERERyShKYkREREREJKMoiRERERERkYyiJEZERERERDJKWiQxZradmb1kZnOjn60qOe7U6Ji5ZnZqzPaGZjbOzOaY2Swz+1ndRS8iItsqM2tqZh+Y2RGpjkVERDZLiyQGuASY6u49ganRehlmth1wJTAY2B24MibZuRxY7O69gD7Aq3UStYiIpCUzG29mi83sk3LbDzGz2Wb2mZltUdZU4GJgUnKiFBGRrZWT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\n",
"text/plain": [
"<Figure size 960x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"grad = np.array(grad_val)\n",
"means = np.array(means)\n",
"variances = np.array(variances)\n",
"n = np.array(selected_qubit)\n",
"print(\"我们接着画出这个采样出来的梯度的统计结果:\")\n",
"fig = plt.figure(figsize=plt.figaspect(0.3))\n",
"\n",
"\n",
"# ============= 第一张图 =============\n",
"# 统计出随机采样的梯度平均值和量子比特数量的关系\n",
"plt.subplot(1, 2, 1)\n",
"plt.plot(n, means, \"o-.\")\n",
"plt.xlabel(r\"Qubit #\")\n",
"plt.ylabel(r\"$ \\partial \\theta_{i} \\langle 0|H |0\\rangle$ Mean\")\n",
"plt.title(\"Mean of {} sampled graident\".format(samples))\n",
"plt.xlim([1,9])\n",
"plt.ylim([-0.06, 0.06])\n",
"plt.grid()\n",
"\n",
"# ============= 第二张图 =============\n",
"# 统计出随机采样的梯度的方差和量子比特数量的关系\n",
"plt.subplot(1, 2, 2)\n",
"plt.semilogy(n, variances, \"v\")\n",
"\n",
"# 多项式拟合\n",
"fit = np.polyfit(n, np.log(variances), 1)\n",
"slope = fit[0] \n",
"intercept = fit[1] \n",
"plt.semilogy(n, np.exp(n*slope + intercept), \"r--\", label=\"Slope {:03.4f}\".format(slope))\n",
"plt.xlabel(r\"Qubit #\")\n",
"plt.ylabel(r\"$ \\partial \\theta_{i} \\langle 0|H |0\\rangle$ Variance\")\n",
"plt.title(\"Variance of {} sampled graident\".format(samples))\n",
"plt.legend()\n",
"plt.xlim([1,9])\n",
"plt.ylim([0.0001, 0.1])\n",
"plt.grid()\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"要注意的是,在理论上,只有当我们选取的网络结构还有损失函数满足一定条件时 (2-design)详见论文 [[1]](https://arxiv.org/abs/1803.11173), 才会出现这种效应。接着我们不妨可视化一下不同量子比特数量对的优化曲面的影响:\n",
"\n",
"![BP-fig-qubit_landscape_compare](./figures/BP-fig-qubit_landscape_compare.png \"(a)不固定 z 轴尺度时,采样出的优化曲面分别从左至右对应2、4和6量子比特的情形。(b)同样的优化曲面但是固定 z 轴尺度作为对比。\")\n",
"<div style=\"text-align:center\">(a)不固定 z 轴尺度时,采样出的优化曲面分别从左至右对应2、4和6量子比特的情形。(b)同样的优化曲面但是固定 z 轴尺度作为对比。</div>\n",
" \n",
"\n",
"画图时 $\\theta_1$ 和 $\\theta_2$ 是前两个电路参数, 剩余参数全部固定为 $\\pi$。不然我们画不出这个高维度的流形。\n",
"结果不出所料,陡峭程度随着 $n$ 的增大越来越小了,**注意到 Z 轴尺度的极速减小**。相对于2量子比特的情况,6量子比特的优化曲面已经非常扁平了。\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_______\n",
"\n",
"## 参考文献\n",
"\n",
"[1] McClean, J. R., Boixo, S., Smelyanskiy, V. N., Babbush, R. & Neven, H. Barren plateaus in quantum neural network training landscapes. [Nat. Commun. 9, 4812 (2018).](https://www.nature.com/articles/s41467-018-07090-4)\n",
"\n",
"[2] Cerezo, M., Sone, A., Volkoff, T., Cincio, L. & Coles, P. J. Cost-Function-Dependent Barren Plateaus in Shallow Quantum Neural Networks. [arXiv:2001.00550 (2020).](https://arxiv.org/abs/2001.00550)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_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_minor": 4
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Barren Plateaus\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"In the training of classical neural networks, gradient-based optimization methods encounter the problem of local minimum and saddle points. Correspondingly, the Barren plateau phenomenon could potentially block us from efficiently training quantum neural networks. This peculiar phenomenon was first discovered by McClean et al. in 2018 [[arXiv:1803.11173]](https://arxiv.org/abs/1803.11173). In few words, when we randomly initialize the parameters in random circuit structure meets a certain degree of complexity, the optimization landscape will become very flat, which makes it difficult for the optimization method based on gradient descent to find the global minimum. For most variational quantum algorithms (VQE, etc.), this phenomenon means that when the number of qubits increases, randomly choose a circuit ansatz and randomly initialize the parameters of it may not be a good idea. This will make the optimization landscape corresponding to the loss function into a huge plateau, which makes the quantum neural network's training much more difficult. The initial random value for the optimization process is very likely to stay inside this plateau, and the convergence time of gradient descent will be prolonged.\n",
"\n",
"![BP-fig-barren](./figures/BP-fig-barren.png)\n",
"\n",
"The figure is generated through [Gradient Descent Viz](https://github.com/lilipads/gradient_descent_viz)\n",
"\n",
"This tutorial mainly discusses how to show the barren plateau phenomenon with Paddle Quantum. Although it does not involve any algorithm innovation, it can improve readers' understanding about gradient-based training for quantum neural network. We first introduce the necessary libraries and packages:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:13:41.746113Z",
"start_time": "2021-03-02T12:13:39.017668Z"
}
},
"outputs": [],
"source": [
"import time\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt \n",
"import paddle\n",
"from paddle import matmul as matmul\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import dagger\n",
"from paddle_quantum.state import density_op"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Random network structure\n",
"\n",
"Here we follow the original method mentioned in the paper by McClean (2018) and build the following random circuit (currently we do not support the built-in control-Z gate, use CNOT instead):\n",
"\n",
"![BP-fig-Barren_circuit](./figures/BP-fig-Barren_circuit.png)\n",
"\n",
"First, we rotate all the qubits around the $y$-axis of the Bloch sphere with rotation gates $R_y(\\pi/4)$.\n",
"\n",
"The remaining structure forms a block, each block can be further divided into two layers:\n",
"\n",
"- Build a layer of random rotation gates on all the qubits, where $R_{\\ell,n} \\in \\{R_x, R_y, R_z\\}$. The subscript $\\ell$ means the gate is in the $\\ell$-th repeated block. In the figure above, $\\ell =1$. The second subscript $n$ indicates which qubit it acts on.\n",
"- The second layer is composed of CNOT gates, which act on adjacent qubits.\n",
"\n",
"In Paddle Quantum, we can build this circuit with the following code:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:13:41.776722Z",
"start_time": "2021-03-02T12:13:41.749182Z"
}
},
"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"
]
}
],
"source": [
"def rand_circuit(theta, target, num_qubits):\n",
"\n",
" # We need to convert Numpy array to Tensor in PaddlePaddle\n",
" const = paddle.to_tensor(np.array([np.pi/4]))\n",
" \n",
" # Initialize the quantum circuit\n",
" cir = UAnsatz(num_qubits)\n",
" \n",
" # ============== First layer ==============\n",
" # Fixed-angle Ry rotation gates \n",
" for i in range(num_qubits):\n",
" cir.ry(const, i)\n",
"\n",
" # ============== Second layer ==============\n",
" # Target is a random array help determine rotation gates\n",
" for i in range(num_qubits):\n",
" if target[i] == 0:\n",
" cir.rz(theta[i], i)\n",
" elif target[i] == 1:\n",
" cir.ry(theta[i], i)\n",
" else:\n",
" cir.rx(theta[i], i)\n",
" \n",
" # ============== Third layer ==============\n",
" # Build adjacent CNOT gates\n",
" for i in range(num_qubits - 1):\n",
" cir.cnot([i, i + 1])\n",
" \n",
" return cir.U"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Loss function and optimization landscape\n",
"\n",
"After determining the circuit structure, we also need to define a loss function to determine the optimization landscape. Following the same set up with McClean (2018), we take the loss function from VQE:\n",
"\n",
"$$\n",
"\\mathcal{L}(\\boldsymbol{\\theta})= \\langle0| U^{\\dagger}(\\boldsymbol{\\theta})H U(\\boldsymbol{\\theta}) |0\\rangle,\n",
"\\tag{1}\n",
"$$\n",
"\n",
"The unitary matrix $U(\\boldsymbol{\\theta})$ is the quantum neural network with the random structure we built from the last section. For Hamiltonian $H$, we also take the simplest form $H = |00\\cdots 0\\rangle\\langle00\\cdots 0|$. After that, we can start sampling gradients with the two-qubit case - generate 300 sets of random network structures and different random initial parameters $\\{\\theta_{\\ell,n}^{( i)}\\}_{i=1}^{300}$. Each time the partial derivative with respect to the **first parameter $\\theta_{1,1}$** is calculated according to the analytical gradient formula from VQE. Then analyze the mean and variance of these 300 sampled partial gradients. The formula for the analytical gradient is:\n",
"\n",
"$$\n",
"\\partial \\theta_{j} \n",
"\\equiv \\frac{\\partial \\mathcal{L}}{\\partial \\theta_j}\n",
"= \\frac{1}{2} \\big[\\mathcal{L}(\\theta_j + \\frac{\\pi}{2}) - \\mathcal{L}(\\theta_j - \\frac{\\pi}{2})\\big].\n",
"\\tag{2}\n",
"$$\n",
"\n",
"For a detailed derivation, see [arXiv:1803.00745](https://arxiv.org/abs/1803.00745)."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:13:50.788968Z",
"start_time": "2021-03-02T12:13:41.786234Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The main program segment has run in total 31.41524910926819 seconds\n",
"Use 300 samples to get the mean value of the gradient of the random network's first parameter, and we have: 0.005925709445960606\n",
"Use 300 samples to get the variance of the gradient of the random network's first parameter, and we have: 0.028249053148446363\n"
]
}
],
"source": [
"# Hyper parameter settings\n",
"np.random.seed(42) # Fixed Numpy random seed\n",
"N = 2 # Set the number of qubits\n",
"samples = 300 # Set the number of sampled random network structures\n",
"THETA_SIZE = N # Set the size of the parameter theta\n",
"ITR = 1 # Set the number of iterations\n",
"LR = 0.2 # Set the learning rate\n",
"SEED = 1 # Fixed the randomly initialized seed in the optimizer\n",
"\n",
"# Initialize the register for the gradient value\n",
"grad_info = []\n",
"\n",
"paddle.seed(SEED)\n",
"class manual_gradient(paddle.nn.Layer):\n",
" \n",
" # Initialize a list of learnable parameters and fill the initial value with a uniform distribution of [0, 2*pi]\n",
" def __init__(self, shape, param_attr= paddle.nn.initializer.Uniform(\n",
" low=0.0, high=2 * np.pi),dtype='float64'):\n",
" super(manual_gradient, self).__init__()\n",
" \n",
" # Convert Numpy array to Tensor in PaddlePaddle\n",
" self.H = paddle.to_tensor(density_op(N))\n",
" \n",
" # Define loss function and forward propagation mechanism \n",
" def forward(self):\n",
" \n",
" # Initialize three theta parameter lists\n",
" theta_np = np.random.uniform(low=0., high= 2 * np.pi, size=(THETA_SIZE))\n",
" theta_plus_np = np.copy(theta_np) \n",
" theta_minus_np = np.copy(theta_np) \n",
" \n",
" # Modified to calculate analytical gradient\n",
" theta_plus_np[0] += np.pi/2\n",
" theta_minus_np[0] -= np.pi/2\n",
" \n",
" # Convert Numpy array to Tensor in PaddlePaddle\n",
" theta = paddle.to_tensor(theta_np)\n",
" theta_plus = paddle.to_tensor(theta_plus_np)\n",
" theta_minus = paddle.to_tensor(theta_minus_np)\n",
" \n",
" # Generate random targets, randomly select circuit gates in rand_circuit\n",
" target = np.random.choice(3, N) \n",
" \n",
" U = rand_circuit(theta, target, N)\n",
" U_dagger = dagger(U) \n",
" U_plus = rand_circuit(theta_plus, target, N)\n",
" U_plus_dagger = dagger(U_plus) \n",
" U_minus = rand_circuit(theta_minus, target, N)\n",
" U_minus_dagger = dagger(U_minus) \n",
"\n",
" # Calculate the analytical gradient\n",
" grad = (paddle.real(matmul(matmul(U_plus_dagger, self.H), U_plus))[0][0] \n",
" - paddle.real(matmul(matmul(U_minus_dagger, self.H), U_minus))[0][0])/2 \n",
" \n",
" return grad\n",
"\n",
"# Define the main block\n",
"def main():\n",
"\n",
" # Set the dimension of QNN\n",
" sampling = manual_gradient(shape=[THETA_SIZE])\n",
" \n",
" # Sampling to obtain gradient information\n",
" grad = sampling() \n",
" \n",
" return grad.numpy()\n",
"\n",
"# Record running time\n",
"time_start = time.time()\n",
"\n",
"# Start sampling\n",
"for i in range(samples):\n",
" if __name__ == '__main__':\n",
" grad = main()\n",
" grad_info.append(grad)\n",
"\n",
"time_span = time.time() - time_start\n",
"\n",
"print('The main program segment has run in total ', time_span, ' seconds')\n",
"print(\"Use \", samples, \" samples to get the mean value of the gradient of the random network's first parameter, and we have:\", np.mean(grad_info))\n",
"print(\"Use \", samples, \"samples to get the variance of the gradient of the random network's first parameter, and we have:\", np.var(grad_info))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Visualization of the Optimization landscape\n",
"\n",
"Next, we use Matplotlib to visualize the optimization landscape. In the case of **two qubits**, we only have two parameters $\\theta_1$ and $\\theta_2$, and there are 9 possibilities for the random circuit structure in the second layer. \n",
"\n",
"![BP-fig-landscape2](./figures/BP-fig-landscape2.png)\n",
"\n",
"The plain structure shown in the $R_z$-$R_z$ layer from the last figure is something we should avoid. In this case, it's nearly impossible to converge to the theoretical minimum. If you want to try to draw some optimization landscapes yourself, please refer to the following code:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:14:18.147473Z",
"start_time": "2021-03-02T12:14:14.551262Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 960x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"The main program segment has run in total 14.537230014801025 seconds\n"
]
}
],
"source": [
"# Introduce the necessary packages\n",
"from matplotlib import cm\n",
"from mpl_toolkits.mplot3d import Axes3D\n",
"from matplotlib.ticker import LinearLocator, FormatStrFormatter\n",
"\n",
"time_start = time.time()\n",
"N = 2\n",
"\n",
"# Set the image ratio Vertical: Horizontal = 0.3\n",
"fig = plt.figure(figsize=plt.figaspect(0.3))\n",
"\n",
"# Generate points on the x, y axis\n",
"X = np.linspace(0, 2*np.pi, 80)\n",
"Y = np.linspace(0, 2*np.pi, 80)\n",
"\n",
"# Generate 2D mesh\n",
"xx, yy = np.meshgrid(X, Y)\n",
"\n",
"\n",
"# Define the necessary logic gates\n",
"def rx(theta):\n",
" mat = np.array([[np.cos(theta/2), -1j*np.sin(theta/2)],\n",
" [-1j*np.sin(theta/2), np.cos(theta/2)]])\n",
" return mat\n",
"\n",
"def ry(theta):\n",
" mat = np.array([[np.cos(theta/2), -1*np.sin(theta/2)],\n",
" [np.sin(theta/2), np.cos(theta/2)]])\n",
" return mat\n",
"\n",
"def rz(theta):\n",
" mat = np.array([[np.exp(-1j*theta/2), 0],\n",
" [0, np.exp(1j*theta/2)]])\n",
" return mat\n",
"\n",
"def CNOT():\n",
" mat = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]])\n",
" return mat\n",
"\n",
"# ============= The first figure =============\n",
"# We visualize the case where the second layer is kron(Ry, Ry)\n",
"ax = fig.add_subplot(1, 2, 1, projection='3d')\n",
"\n",
"# Forward propagation to calculate loss function:\n",
"def cost_yy(para):\n",
" L1 = np.kron(ry(np.pi/4), ry(np.pi/4))\n",
" L2 = np.kron(ry(para[0]), ry(para[1]))\n",
" U = np.matmul(np.matmul(L1, L2), CNOT())\n",
" H = np.zeros((2 ** N, 2 ** N))\n",
" H[0, 0] = 1\n",
" val = (U.conj().T @ H@ U).real[0][0]\n",
" return val\n",
"\n",
"# Draw an image\n",
"Z = np.array([[cost_yy([x, y]) for x in X] for y in Y]).reshape(len(Y), len(X))\n",
"surf = ax.plot_surface(xx, yy, Z, cmap='plasma')\n",
"#cset = ax.contourf(xx, yy, Z, zdir='z', offset=np.min(Z), cmap='viridis')\n",
"ax.set_xlabel(r\"$\\theta_1$\")\n",
"ax.set_ylabel(r\"$\\theta_2$\")\n",
"ax.set_title(\"Optimization Landscape for Ry-Ry Layer\")\n",
"#fig.colorbar(surf, shrink=0.5, aspect=5)\n",
"\n",
"# ============= The second figure =============\n",
"# We visualize the case where the second layer is kron(Rx, Rz)\n",
"ax = fig.add_subplot(1, 2, 2, projection='3d')\n",
"\n",
"\n",
"def cost_xz(para):\n",
" L1 = np.kron(ry(np.pi/4), ry(np.pi/4))\n",
" L2 = np.kron(rx(para[0]), rz(para[1]))\n",
" U = np.matmul(np.matmul(L1, L2), CNOT())\n",
" H = np.zeros((2 ** N, 2 ** N))\n",
" H[0, 0] = 1\n",
" val = (U.conj().T @ H@ U).real[0][0]\n",
" return val\n",
"\n",
"Z = np.array([[cost_xz([x, y]) for x in X] for y in Y]).reshape(len(Y), len(X))\n",
"surf = ax.plot_surface(xx, yy, Z, cmap='viridis')\n",
"#cset = ax.contourf(xx, yy, Z, zdir='z', offset=np.min(Z), cmap='viridis')\n",
"ax.set_xlabel(r\"$\\theta_1$\")\n",
"ax.set_ylabel(r\"$\\theta_2$\")\n",
"ax.set_title(\"Optimization Landscape for Rx-Rz Layer\")\n",
"\n",
"\n",
"plt.show()\n",
"\n",
"time_span = time.time() - time_start \n",
"print('The main program segment has run in total ', time_span, ' seconds')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## More qubits\n",
"\n",
"Then, we will see what happens to the sampled gradients when we increase the number of qubits"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:18:13.493641Z",
"start_time": "2021-03-02T12:15:55.484851Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The main program segment has run in total 245.28915309906006 seconds\n"
]
}
],
"source": [
"# Hyper parameter settings\n",
"selected_qubit = [2, 4, 6, 8]\n",
"samples = 300\n",
"grad_val = []\n",
"means, variances = [], []\n",
"\n",
"# Record operation time\n",
"time_start = time.time()\n",
"\n",
"# Keep increasing the number of qubits\n",
"for N in selected_qubit:\n",
" grad_info = []\n",
" THETA_SIZE = N\n",
" for i in range(samples):\n",
" class manual_gradient(paddle.nn.Layer):\n",
" \n",
" # Initialize a list of learnable parameters of length THETA_SIZE\n",
" def __init__(self, shape, param_attr=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi),dtype='float64'):\n",
" super(manual_gradient, self).__init__()\n",
"\n",
" # Convert to Tensor in PaddlePaddle\n",
" self.H = paddle.to_tensor(density_op(N))\n",
"\n",
" # Define loss function and forward propagation mechanism \n",
" def forward(self):\n",
"\n",
" \n",
" # Initialize three theta parameter lists\n",
" theta_np = np.random.uniform(low=0., high= 2 * np.pi, size=(THETA_SIZE))\n",
" theta_plus_np = np.copy(theta_np) \n",
" theta_minus_np = np.copy(theta_np) \n",
"\n",
" \n",
" # Modify to calculate analytical gradient\n",
" theta_plus_np[0] += np.pi/2\n",
" theta_minus_np[0] -= np.pi/2\n",
"\n",
" # Convert to Tensor in PaddlePaddle\n",
" theta = paddle.to_tensor(theta_np)\n",
" theta_plus = paddle.to_tensor(theta_plus_np)\n",
" theta_minus = paddle.to_tensor(theta_minus_np)\n",
"\n",
" # Generate random targets, randomly select circuit gates in rand_circuit\n",
" target = np.random.choice(3, N) \n",
" \n",
" U = rand_circuit(theta, target, N)\n",
" U_dagger = dagger(U) \n",
" U_plus = rand_circuit(theta_plus, target, N)\n",
" U_plus_dagger = dagger(U_plus) \n",
" U_minus = rand_circuit(theta_minus, target, N)\n",
" U_minus_dagger = dagger(U_minus) \n",
"\n",
" \n",
" # Calculate analytical gradient\n",
" grad = (paddle.real(matmul(matmul(U_plus_dagger, self.H), U_plus))[0][0] \n",
" - paddle.real(matmul(matmul(U_minus_dagger, self.H), U_minus))[0][0])/2\n",
" \n",
" return grad \n",
" \n",
" \n",
" # Define the main program segment \n",
" def main():\n",
" \n",
" # Set the dimension of QNN\n",
" sampling = manual_gradient(shape=[THETA_SIZE])\n",
" \n",
" # Sampling to obtain gradient information\n",
" grad = sampling()\n",
" \n",
" return grad.numpy()\n",
" \n",
" if __name__ == '__main__':\n",
" grad = main()\n",
" grad_info.append(grad)\n",
" \n",
" # Record sampling information\n",
" grad_val.append(grad_info) \n",
" means.append(np.mean(grad_info))\n",
" variances.append(np.var(grad_info))\n",
"\n",
"time_span = time.time() - time_start \n",
"print('The main program segment has run in total ', time_span, ' seconds')"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-02T12:19:16.260635Z",
"start_time": "2021-03-02T12:19:15.034594Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"We then draw the statistical results of this sampled gradient:\n"
]
},
{
"data": {
"image/png": "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IiIJlpeXx7Rp0xg3bhxt27ZlxIgR3FeSFEXef/99hgwZQtu2bcnJyeHkk0/mtddeA0KNx4gRIwA45ZRTeOONNygqKuKtt97i+OOPp3///vzmN79hwYIFCY373XffpUmTJuy8884AbNy4kXnz5rHXXnvx4Ycfsueee/L73/++dN/cuXMpLCxkwoQJnHnmmaxcuZK77rqLww47jPz8/ITGFkt9YkRERERk21dYWPm+Jk2q3t+mTdX7K5Gdnc2QIUMYMmQI/fr14/777+e0006r8XkgDElcXFxMy5YtSzvcV2bYsGEsWrSI3Xbbjbvvvpvvv/+ejRs3kpOTw7x58+jYsWOl7504cWJpLQxA69atadKkCcceeywAxx9/PPfeey8QanUGDx5MgwYN6NatG7169WLu3Lm8/fbbvP7669x1110UFRWxfv168vLyuOGGG7bqs1dENTEiIiK1pD4xIlLe7NmzmTt3bun69OnT6dKlS5ljdt99d1599VWWLl3Kpk2bmDBhAj/96U+B0CTrscceA+Dhhx9mn332oXnz5nTr1o1HH30UCP1d/vvf/25x7SlTpjB9+nTuuecezIz99tuv9Fz3338/Rx99dIUxFxcXM2nSpDL9YcyMI488ksIoiZs6dSp9+vQBYPjw4aXbly5dypw5c+jevTsPPfQQ33zzDV999RVjxozhl7/8ZUITGFASIyIiUmvqEyMi5RUVFXHqqafSp08fdtllFz799FNGjx5d5pj27dtzww03sP/++7PrrrsyaNCg0gSjadOmvPfee+y88868/PLLXHHFFUAYCvnee+9l1113pW/fvjz99NPVxnLVVVcxduxYevTowbJlyzj99NMBmDx5cul5AV577TU6depE9+7dy7z/xhtvZPTo0eyyyy48+OCD3HLLLUCo8WndujV9+vRh//335+abb6Z169Zb/Z3VhJqTiYiIiIgk2KBBg3jrrbcq3FcY0zTtxBNPLNN8K9bYsWO32NatW7fSDvTx6tatG++9994W24866iiOOuqo0vUhQ4bwzjvvbHFcly5dSvvqxDIzxo4dW2GcJU477bStbkJXFdXEiIiIiIhIRlESIyIiIiKSZtTHrmpKYkRERERkm+TuqQ5BKlHb342SGBERkVrS6GQi6Sc3N5dly5YpkUlD7s6yZcvIzc3d6nOoY7+IiEgtufszwDMFBQVnpjoWEQny8/OZN28eS5YsSdo11q5dW6s/xOtKOsaZm5tbq8kwlcSIiIiIyDanZALGZCosLGTAgAFJvUYiZEqcNaHmZCIiIiIiklGUxIiIiIiISEZREiMiIiIiIhlFSYyIiIiIiGQUJTEiIiK1pCGWRUTqlpIYERGRWnL3Z9x9ZF5eXqpDERGpF5TEiIiIiIhIRlESIyIiIiIiGSWtkhgzO8TMZpvZZ2Z2SQX7G5nZI9H+d82sa7n9nc2syMx+X2dBi4iIiIhIncpJdQAlzCwbuBM4CJgHvG9mk93905jDTgdWuHsPMzsBuBEYEbN/LPDvuopZREQkUxx2++t8umDV5g0vPAdAn/bNef78fVMUlYjI1kmnmpjdgc/c/Qt3Xw9MBI4ud8zRwP3R8mPAUDMzADMbDnwJzKibcEVERDLHwM4taZBtZbY1yDYGdmmVoohERLZeOiUxHYFvY9bnRdsqPMbdNwLfA63NLA+4GLiqDuIUERHJOOcN7UmWlU1iss04b2iPFEUkIrL10qY5WS2NBm519yIrd4Muz8xGAiMB2rZtS2FhYdKDq62ioiLFmWCZEqviTKxMiRMyK1bJDO2a53L8oHwe+eBbNmxyGmQbx+3WiXbNclMdmohIjaVTEjMf6BSznh9tq+iYeWaWA7QAlgGDgePM7CagJVBsZmvd/Y7yF3H3ccA4gIKCAh8yZEiCP0biFRYWojgTK1NiVZyJlSlxQmbFKmGyS+DIDh06pDqUKp03tCePTpsHuGphRCSjpVNzsveBnmbWzcwaAicAk8sdMxk4NVo+DnjZg33dvau7dwVuA/5cUQIjIiKSDJky2WW75rmcslNLLnj9IU7u00q1MCKSsdKmJsbdN5rZKGAKkA2Md/cZZnY18IG7TwbuBR40s8+A5YRER0REROJ03vrPaPHWBIrnToU118GvfgXZ2akOS0SkRtImiQFw9+eB58ttuyJmeS1wfDXnGJ2U4ERERLYBLX71C6at+4FBDz4IZ54Jd9wBt90Gar4oIhkknZqTiYiISB1Y3bs3vPEGTJwIK1bAjTemOiQRkRpREiMiIlIfmcGIETBrFowfH7Z9+SVccgmsWlX1e0VEUkxJjIiISH3WuDG0bx+Wp0yBm26Cnj3h7rth06bUxiYiUgklMSIiIhKcdRa8/z706gUjR8LAgfDKK6mOSkRkC0piREREZLNBg+C112DSJPj+e3jssVRHJCKyBSUxIiIiUpYZHH88zJwJ118ftr31Flx0UUhsRERSTEmMiIiIVKxxY2jePCy//jqMGRP6y4wbp/4yIpJSSmJERESkehdfDB98AL17w29+E/rLFBamOioRqaeUxIiIiEh8Bg6EV18N/WRWrQpJjYhICuSkOgAREZFMZ2ZHAkd26NAh1aEknxn87Gdw+OGQFT0LnTgxJDR//CO0bJnS8ESkflBNjIiISC25+zPuPjIvLy/VodSd3Fxo2DAsf/wxjB0b+sv84x+wcWNqYxORbZ6SGBEREamd664LNTF9+oS5ZgYODAMBiIgkiZIYERERqb2Sjv6PPQZFRbB4caojEpFtmPrEiIiISGKU9Jc54ojNTc1uugkWLoQrrlB/GRFJGNXEiIiISGI1ahQSGoDvvoPbboMePeBvf1N/GRFJCCUxIiIikjy33QYffgg77wznnAP9+8M776Q6KhHJcEpiREREJLn694dXXoEnnoB16yAnas3untKwRCRzKYkRERGR5DODY46BWbNgt93CtnPOgd/9DlasSG1sIpJxlMSIiIhI3cnODj+Li8PP224L88vceaf6y4hI3JTEiIiISN3Lygod/T/6CPr1g1GjYNddw7qISDWUxIiIiEjq7LorvPwyPPlkqKVp2zZsL6mpERGpgOaJERGRtGJmBpwMdHf3q82sM7CDu7+X4tAkWcxg+HA4+uiw7A6HHsqOzZuHJKdVq1RHKCJpRjUxIiKSbu4C9gROjNZXA3emLhypMyVzy6xfD926kf/EE2F+GfWXEZFylMSIiEi6Gezu5wJrAdx9BdAwtSFJnWrUCP7+dz4YNy4Mz1zSX2b27FRHJiJpQkmMiIikmw1mlg04gJm1BdRBoh76Yccd4T//gaefDn1lOnYMO9avT21gIpJySmJERCTd/AV4EmhnZtcBbwB/Tm1IkjJmcNRRUFgIeXkhgRkwAM47D5YvT3V0IpIiSmJERCStuPtDwEXA9cACYLi7P5raqCRtrFsH++0X+sn06AF//Sts2JDqqESkjimJERGRtOPus9z9Tne/w91npjoeSSPNmoX5ZaZPh4EDQ43MLrvAvHmpjkxE6lBaJTFmdoiZzTazz8zskgr2NzKzR6L975pZ12j7QWY2zcw+jn4eUOfBi4hIQpjZ/WbWMma9lZmNT0Ecw83s7qjcObiury/V6NcPXnoJJk8Oyx06hO1FRamNS0TqRNokMVEnzjuBQ4E+wIlm1qfcYacDK9y9B3ArcGO0fSlwpLv3A04FHqybqEVEJAl2cfeVJSvR6GQDanICMxtvZovN7JNy26t8WBbL3Z9y9zOBs4ARNbm+1BEzOPJImDQJsrJg2TLo3h3+7//Csohss+JOYqJakJPM7DIzu6LklcBYdgc+c/cv3H09MBE4utwxRwP3R8uPAUPNzNz9I3f/Lto+A2hsZo0SGJuIiNSdLDMrnd3QzLaj5pMz3wccEruhsodlZtbPzJ4t92oX89Y/onlqMoMZHHcc3HVX6C9z++3qLyOyjTJ3j+9AsxeA74FpwKaS7e5+S0ICMTsOOMTdz4jWf0GYK2BUzDGfRMfMi9Y/j45ZWu48Z7n7gZVcZyQwEqBt27aDJk2alIjwk6qoqIi8vLxUh1GtTIkTMidWxZlYmRInZE6s+++//zR33y2R5zSzXwKXA5MAA44D/uzuD9TwPF2BZ91952h9T2C0uw+L1i8FcPfrK3m/ATcAL7n7f6q4jsqVJNnaOJt++SU73nkn202bxppOnZh2111sSuLnzZTvEzInVsWZWJkSJ9SgXHH3uF7AJ/EeuzUvQiF1T8z6L4A7yscA5Mesfw60iVnvG23bMZ5r9urVyzPBK6+8kuoQ4pIpcbpnTqyKM7EyJU73zIkV+MCTUyb0AUYB5wJ9tvIcXWPLrnjKmXLvP4/w4O7vhIdjKlfqWK3iLC52f+YZ9wsu2LxtyZJax1SRTPk+3TMnVsWZWJkSp3v85UpN+sS8ZWb9anB8Tc0HOsWs50fbKjzGzHKAFsCyaD2fMK/AL9398yTGKSIiSRQ1B+4PNAdaA8cluPlyXNz9L+4+yN3Pcve/1/X1pZbM4IgjYOzYsD57NnTqBKNGwdKlVb9XRNJeTZKYfYBpUYfI/0Ujgf0vgbG8D/Q0s25m1hA4AZhc7pjJhI77EJ6ovezuHo1i8xxwibu/mcCYRESk7j1N6AO5Efgh5lVb8Tws2ypmdqSZjSvSyFjpq00bOP10+PvfoWdPuO22MHGmiGSkmnSUPDRpUQDuvtHMRgFTgGxgvLvPMLOrCdVKk4F7gQfN7DNgOSHRgdDkoAcQO9jAwe6+OJkxi4hIUuS7+yHVH1ZjpQ/LCMnLCcBJiTixuz8DPFNQUHBmIs4nSdC6NdxxB5x9NlxwQXjdey98+CE0aJDq6ESkhuJOYtz962i0mJ5AbsyurxMVjLs/DzxfbtsVMctrgeMreN+1wLWJikNERFLqLTPr5+4fb+0JzGwCMARoY2bzgCvd/d6KHpYlJGLJHH37wpQp8PzzoYlZSQLzzTfQuXNqYxORuMWdxJjZGcD5hOr36cAewNuAJpYUEZFE2gc4zcy+BNYRRihzd98l3hO4+4mVbN/iYZnUQ2Zw+OHhBTB1KgwbBr/5DVx1VWh6JiJprSZ9Ys4HfgJ87e77EyYeW5mMoEREpF47lFDrfzBwJHBE9DNtqU9MhuvfPzQz+8c/wvwyt96q/jIiaa4mfWLWuvtaM8PMGrn7LDMrSFpkIiJSL9VF8+VEU5+YDNe6Nfz1ryGR+d3vwuvRR+HNN0OtTQUOu/11Pl2wavOGF54DoE/75jx//r51EbVIvVaTJGZeNArYU8BLZraCNC5QREQkM6n5sqRMnz7wwgvw73/DqlUhgdm0CebMgZ12KnPowM4tmbt4NRs2bZ40vEG2MbBLq7qOWqReirs5mbsf4+4r3X008CfCSGHDkxSXiIjUX2q+LKl16KEwYkRYvv9+2HlnOOccWLKk9JDzhvYkq1wtTbYZ5w3tUZeRitRbcScxFpxiZle4+6uEp2P9kxWYiIjUW2uj0ShLmy8Dad18WX1itmHDh4cJMseNC/PLjB0L69fTrnkuxw/Kp0F2SGQaZBvH7daJds1yqz6fiCRETTr23wXsCZSM+LIauDPhEYmISH1Xvvny06R582V3f8bdR+bl5aU6FEm07baD22+Hjz+GvfaCCy+En/0MKFsbo1oYkbpVkz4xg919oJl9BODuK8ysYZLiEhGResrdj4kWR5vZK0AL4IUUhiQS+sQ8/3zoL9O4MQDtsjYyqs0axi7MVS2MSB2rSRKzwcyyAQcws7ZAcVKiEhERAaLmyyLp49BDNy/fcgujrr6abj8ZxuCRf09dTCL1UE2ak/0FeBJoZ2bXAW8Af05KVCIiUu+Y2RvRz9VmtirmtdrMVlX3fpE693//h40axWEfvEjbAf1gzBhYty7VUYnUC3HXxLj7Q2Y2DRhKmD15uLvPTFpkIiJSr7j7PmZmQF93/ybV8dSEmR0JHNmhQ4dUhyJ1Keov88GgQew+aRL84Q8wYwb885+pjkxkm1eT5mREI8TMSlIsIiJSz7m7m9lzQL9Ux1ITmuyyflvTuTM8+yxMmQL5+WHjvHmwbBnsumtqgxPZRlWbxJjZ5Kr2u/tRiQtHRESED83sJ+7+fqoDEamRYcM2L191FYwfD2ecAddcA+3apS4ukW1QPDUxewLfAhOAdwlNyURERJJlMHCymX0N/EAod9zdd0ltWCI1cNNNkJcHd9wBEybAn/4E550HjRqlOjKRbUI8ScwOwEGE+WFOAp4DJrj7jGQGJiIi9daw6g8RSXOtWsGtt8JZZ4W5ZS66KDQvu+GGVEcmsk2oNolx902E8flfMLNGhGSm0Myucvc7kh2giIjUL+7+tZm1AnoCsRNvpPWElyIVKijY3F+mf/+w7eOPobhY/WVEaiGuIZbNrJGZHQv8CziXzcMti4iIJJSZnQG8BkwBrop+jk5lTNUxsyPNbFxRUVGqQ5F0NWwYbL99WL70UhgwAEaOhEWLUhuXSIaqNokxsweAt4GBwFXu/hN3v8bd5yc9OhERqY/OB34CfO3u+wMDgJUpjaga7v6Mu4/My8tLdSiSCR58EC64IAzF3LNn6D+j+WVEaiSemphTCFX65wNvafKxuvPUR/PZ+4aXOe2FH9j7hpd56iPljSJSL6x197UQWgJEw/sXpDgmkcRp1QpuuSXMKbP//nDxxfCPf6Q6KpGMEk+fmLianEliPfXRfC594mN+3LAJgPkrf+TSJz4GYPiAjqkMTUQk2eaZWUvgKeAlM1uB+sPItqhXL3j6aXj5Zdhrr7DtlVegZcvQ3ExEKqUEJU3dPGV2aQJT4scNm7j+3zNx9xRFJSKSfO5+jLuvdPfRwJ+Ae4HhKQ1KJJkOOAByc8E91MoMGhTml1m4MNWRiaSteIZYlhT4buWPFW5ftGod/Ua/SO8dmtG7fTN679Ccndo3p/cOzWjaSL9OEclcZnYn8LC7v1myzd1fTWFIInXLDF58Ea69Fv7yF5g0CS6/HM4/PyQ5IlJKNTFpqkPLxhVub9m4AccO7IgZPP3Rd/zxqU/42d/e4l/vhJYWS4vWcetLc/h62Q91Ga6ISCLMAcaY2VdmdpOZqT2N1D8tW8KYMZv7y1xyCTz3XKqjEkk7enSfpv4wrKBMnxiAxg2yGX1U39I+Me7O/JU/MmvBanpuH0bEmbNoNX95eS5792hDl9ZNmTpzEXe88hm9d2hOn/bN6N2+OQU7NKN5boOUfC4Rkcq4++3A7WbWBTgBGG9mjYEJhEmW56Q0wCqY2ZHAkR06dEh1KLKt6Nkz9Jd5+23YY4+w7ZFHwvaBA1Mbm0gaiCuJiSYdOxI4BugFfAk8DTzt7ouTF179VZKo3DxlNvNX/kjHlo35w7CCMp36zYz8Vk3Ib9WkdNteO7bh06sOISfbAMgyo2F2Fs9/vIAJ731Telx+q8ZlEpshBW1p0lA5rYiknrt/DdwI3BjVxowHrgCyUxpYFdz9GeCZgoKCM1Mdi2xj9twz/Ny4ES67DL78En71K7juOthhh9TGJpJC1f7VamZPAK2A54CL3X2OmXUGjgb+ZWYN3X1IcsOsn4YP6MjwAR0pLCxkyJAhcb+vccPN5fz+vduxf+92uDsLV61l5oJVzFywmpkLVjFr4WpenrWIYoeP/nQQTRrCpA++5aNvVvLnY3bGzNiwqZgG2Wp1KCJ1x8xygEMJtTFDgULSfLJLkaTLyYFp00Lycvvtob/MZZeF+WbUX0bqoXgevf/a3VfGbnD3b4C/An+NhsGUNGdmtG/RmPYtGnNA7+1Lt6/dsInPlxTRqmlDAOav+JFZC1dhFmpyRj7wAbMXrg6DB5QOJNCMrq2bkqPkRkQSyMwOAk4EDgPeAyYCI91dnfxEIPSXuflm+M1v4Pe/D0nMAQfA4MGpjkykzsUzT8xKM+tNqHkpacs0H5js7jPLJzi1YWaHALcTmgzc4+43lNvfCHgAGAQsA0a4+1fRvkuB04FNwHnuPiVRcW3Lchtk07dDi9L1Cw7qxQUH9SpdP7DP9jRv3IBZC1bz6pwlbCwOwzs3ysmi1/bN6L1DM/bo3pqfDcqv89hFZJtzKfAwcKG7r0h1MCJpq0cPeOqp0Pm/b9+w7fbbYZ99wvDMIvVAPM3JLiY8GZtIeDIGkA9MMLOJ5RONrWVm2cCdwEHAPOB9M5vs7p/GHHY6sMLde5jZCYQ20yPMrA+h2UFfoAPwHzPr5e5lJ1qRGjt5cBdOHtwFgHUbN/HZ4iJmLVjNrIWhWdrLsxbz/Y8bSpOYY+96k4P67MDZQ3bE3flscRFd2zRVk7Rt1FMfzd/cb+udl7fotyVSE+5+QKpjEMkoJQlMURHceGNoWnbaaaHJWfv2KQ1NJNniaU52OtDX3TfEbjSzscAMICFJDLA78Jm7fxGdfyKh9ic2iTmaze2iHwPusNDu6WhgoruvA740s8+i872doNgEaJQTam1ia24gNEkDKHana+umtMkLTdOWFK3joFtfo2F2Fj3a5bFT+9AUraRJWuu8RnX+GSRxnvpofpkR9Oav/JFLn/gYQIlMLSgxFJEay8uDmTPhz3+G224r21+mccVTNohkuniSmGJC7cbX5ba3j/YlSkfg25j1eUD5Rp6lx7j7RjP7HmgdbX+n3HsrLPXNbCQwEqBt27YUFhYmIvakKioqyog41/zwA0dtb1C0ksLCz/lxozNyl0Z8u7qYb1f/wNQZq3n8Qy89vkUjo1NeFod1b0Cf1tmlTdVysizpsWbKd5oucRa78+NGWLPB+XFjWL7jo7X8uKHscT9u2MQ1T/+XhV/OYsmaYrKzjCyDLIPs6GfJcrYZO7UOg1As+qGY9cXQqVmosVv6YzEbi8seb9F7Yrc1zK7Zv5V0+T4r89Z3G7jvk/Wsj+6s81f+yEWPTufTmZ+yVwcNiy4iVWjRItTGjBwJf/gDXHMNnHwydOmS6shEkiKeJOa3wFQzm8vmJKMz0AMYlaS4ksbdxwHjAAoKCrwmo36lSk1HJ0uViuI8tNwxy4rWMWvh6tJR0mYtXMVOOxcwpKAdb362lNP++R4TR+7BoC7b8dXSH/hm+Rp6t29G27xGpYMNJCvWdJSIOIuLndXrNrJ67QZWr90YvcLy/r3b0aJxA975YhmT//sdVxzRh9wG2fzzzS+Z8N43pccXrdsY9/WWr3VmrNuOZz75rsrjmjbMZsbVQwE4b8JHfDz/e175/RAARvzjbd79cnmV7+/Wpmnp8SfdHZ5hPHxmmEvhqDve4Nvla8jOyiIny8iOXuvWZtEsz8jJMnbNb8mNx+1Sev0d2+Zx/oE9ATj7X9PYsKmYLDNyso3srKyQeGVlkZ0Vfg7o1JKf/6QTALe8OJsBnVtyQO/tWb+xmH+8+jnZ2eE6WRZ+ZmdnkR0tZ2UZBds3o19+CzZuKmbqrMX03qEZl7/zbmkCU2J9MTz3TTaXnTQkru9fROq5HXeEJ56Ar78OCYx7mDDz+ONht91SHZ1IwsTTsf8FM+tFaJ4V27H//QT3OZkPdIpZz4+2VXTMvGgIzhaEDv7xvFfSQOu8RuzdoxF792izxb7tm+dy+j7d6dYmTNz57P++Y8yLYW671k0bhhHSdgjz2vTeoRk9t8+jUU7aThuREMXurCpNPsr+XLV2I0N6taXTdk34ZP73jHvtC/4wrIBO2zXh6enzufHfs0ICsn4j7hWf/9n/24cWHVvw9bIfeHHGQn53UC9yG2TTonEDurfJo1luDs1yG0Q/c2jeuAHNo22/fWQ6S1av2+KcHVo25qqj+nLRsAI2FTsbi51idzZucjYVO5vc2VRc9i/1kft1Z/XazYnS+UN7sqRoXZn3bCx2iqPzbSouplnMhK1H7Vp2gsEDd9qeJavXhWtt2hzDdwvW0bptHpuKnbbNNjdnzIlqjEosK1rPD+s3hmtHr43llrOM0iTmwXe+ZmOxc0Dv7Vm7cRO3vFT9nIwj9+tOv/wWrNmwid88OI0/Hr4T3638scJjK9u+LcrUeck02aWknZIamO++g/vug5tuglNPpeERR6Q0LJFEiWt2Q3cvpmxzrWR4H+hpZt0ICcgJwEnljpkMnEro63Ic8LK7u5lNBh6O+ul0AHqyeRACyRA92uVxyaG9S9d/sUdXBnXZLprTJsxr8+A7X7NuY/gDODvL2LFtUx4/ey+a5Tbg2+VraJiTxfbNKx8vvy77GxQXOz+sD8lGRQnI6rUb2GvHNvTv1JJvl6/hyskzOGfIjuzWdTvemLuUs/81jaJ1G/EpL1Z6jb+dPJBO2zWhaN1G/jdvJavWhvZd7ZrlslePNqVJSPPcHJqXJiObk5KOrUJb6RE/6cyIn3QuPe+xA/M5dmDVI85dfthOZfrEADRukM0fhhWwXdOGbBcN2x2PnTuW7We1VwVJblVO2L1zmfXzhvas8LhQs7XlyD1jR/Qvsz7prD1rdP3pVxxcutysUQ5zrzu0TMJTHJsERYlVXm64/TZpkM1z5+1Du2a5/PPNr5hfQcLSoWX9aNOeyfOSabJLSVsdO8LcuaG/zK23MviRR2DWLLjwQvWXkYwWz+hknas7JrLS3VdtbSBRH5dRwBTCEMvj3X2GmV0NfODuk4F7gQejjvvLCYkO0XGTCIMAbATO1chkma9FkwbsuWNr9tyxdem2TcXOl0t/CEnNgtV8vXwNeY3CP+MxL87m/S+X89aloYnSpPe/BYOddmhOz+3zeOGThXF3RHd3fli/iVU/lk8+yjbJ6t+pJQf33YEf1m3ktH++x8mDuzB8QEc+W1zEQbe+WmkNSInLDjP6d2oJwOLVa1mzPsTWoWUuPxuUz/JF8+lX0KO0FqR8EtKqSUgU9ujemsI/7F963vLfWzKUfGelSWHLxuqETpiTqUG20SDOSsKc7KzSwTL+MKyg0sSwntC8ZCLJ0Lw53HADjBzJ8l/9irZ33gnnn5/qqERqJZ6amPvjOMaB+whzuGw1d38eeL7ctitiltcCx1fy3uuA62pzfUl/2VlGj3Z59GiXxxG7lN13+j7dOHKXzU057nnjC+YsKip9n0Hp4AElftywiZunzGb4gI4c//e32KdHW84/sCfrNhaz85VVTzWUnWX8eu+uHNx3BxrlZJX2uwBom9eIUfv3iKkJ2Zx4lNSMNMttQG6D0JG903ZNePb/9i09d/e2eYw+qi+FhUsYsl/3rf26km74gI4MH9AxY/oYpbv6nhjW5bxkIvVS9+7MuOoqhuy8MzRrBhs2wBlnwKhR8JOfpDo6kRqJJ4k5C5jjXt0zZZHU2iW/ZZn1f5+/H98sXxOaoy1YxV9e/qzC95X0N+jeJo92zUM/iUY5WVx+2E7kxSQezXJzSpOPZrk5NG6QXTrYQE52FhNHbm6C1KJJAy48uN48PZcEqs+JYV3NSyZS77WJmuzOnQtTpsADD8AvfxmanHWsHw9NJPPFk8Q8BnQxsznA/4CPS36mcydLkewso1ubpnRr05TD+rXn8Q/nV9nfoGSkKghNgs5M4xoQkW1UXc1LJiIAffrAnDlw/fUwdiw89lgYyezii6Fh/P0aRVKh2mnU3b0f0BY4mzBiTHfgMuB/ZrYwueGJJM4fhhXQuFxHhXrW30Ak3ZXMS1ZeouclE5ESzZuHJGbmTDjssJDIZG/bI3/KtiHe0cnWAe+bWZG7/1/J9mgoTJGMUN/7G4hkgN+yDc1LJpJRuneHRx+FoqKQxKxcCaecAn/6EwwuP/e4SOrFlcTEKNMvxt1XJDAWkaSrz/0NRNJdHc5LJiKVyQtztTF7NkybBnvsEZKZ66+H/KqH3hepS9U2JzOzO83sdDMbACRuynQREZFy3L3Y3d9x98ej1ztKYERSYPDg0F/m0ktDDU2vXnDVVVCslp2SHuKpifkv0B/4JdDMzD4ldLD8FPjU3R9JXngiIlJf1NW8ZCISp2bNwohlZ54ZOvt/8AFkVfv8W6ROVJvEuPu42HUzywf6AbsARwBKYkREJBHqbF4yEamBbt1g0iRYvz6sf/45/PrXcOONobmZSArUtE8M7j4PmAf8O/HhiIhIPaZ5yUTSWcmwy19/HZqa7bknnHxy6C/TqVNqY5N6J54+MZ3jfDWvi4BFRGSb9RjwvZl9YGbjzewCMxtqZu1SHVh1zOxIMxtXVFSU6lBEku+AA8JEmZdfHoZkLiiAa69NdVRSz8RTE6PqfRERSTp372dmjQjNlZ8HfiA0W+5rZrj7DikNsAru/gzwTEFBwZmpjkWkTuTlhcTljDNCf5nFMfOfu4NpLChJrnj6xOxfF4GIiIhoXjKRDNO1KzzyCGyKBhF87TW46CK47Tb1l5GkiqtPjJn1Bo6m7Lj9T7v7rGQFJiIi9ZrmJRPJJNnZ4efq1fDNN6G/zEknwQ03qL+MJEU8fWIuBiYS5oh5L3oZMNHMLklueCIiUl9oXjKRbcDhh4dO/3/8IzzxROgvM2ZMqqOSbVA8NTGnA33dfUPsRjMbS5gv5oZkBCYiIvWO5iUT2Rbk5cE114T+MpdcAjnRn5slE2VqrhlJgHiSmGKgA/B1ue3to30iIiK1pnnJRLYxXbrAhAmhoz/Agw/CnXeG/jJ77ZXS0CTzxZPE/BaYamZzgW+jbZ2BHsCoJMUlIiL1nOYlE9lGlIxU1qwZzJ8Pe+8NJ5wQJsvs3Dm1sUnGimd0shfMrBewO2U79r/v7puSGZyIiNQfZhbvXzMr3X1VUoMRkcQ79lg4+GC46Sa4+WZ46qnQX+bcc1MdmWSgapMYM8ty92LgnWr2i4iI1IbmJRPZ1uXlwdVXb+4v0zF6Pr5+feg7o/4yEqd4mpO9ZGZLgaeA59x9lZk1AQ4BjiG0V+6ftAhFRKRe0LxkIvVI587w8MOb1//8Z3juudBfZu+9UxaWZI54mpMNNbM+hHlinjOzhoQO/VOAW939wyTHKCIi9YTmJROpp3baCe65B/bZB0aMoNHw4amOSNJcXJNduvunhCEurzezxu7+Y3LDEhGR+iaal+xEwtxk70Wb8wnzkk10dw3pL7KtGjECjjgi9JW56SZ2f/JJWLsWTjst1ZFJmooriSnnUjPLAaYD0919TmJDEhGRekrzkonUZ02bwujRcPrpLP31r9l+113D9qIiaNJE/WWkjBr/a3D3K4Dbge+BY8zs7oRHJSIi9VHJvGTlaV4ykfqkUydmXn45DBgQ1keNgt13hzfeSG1cklbiGZ2sK3AusCOwnFAD84y7TyH0ixEREUmE36J5yUSkvGHDYOpU2Hdf+PnPw/wyXbumOipJsXhqYp4GZgF3AgcBuwKvmdmdZtYomcGJiEj94e4vAL2AqwgPyaYAo4GCaJ+I1EcnngizZoWmZs88A717wxNPpDoqSbF4kphsd7/X3acCy939TEKtzFfAuGQGJyIi9UfJvGPu/o67Px693imZWNnM1CBepL5q2hSuvBLmzIGTToI99gjbly6FYrU2rY/iKRD+Y2Yl1fgO4O4b3f1mYM9EBGFm25nZS2Y2N/rZqpLjTo2OmWtmp0bbmpjZc2Y2y8xmmJk6foqIZKaXzOwRMzvRzJpD6T3+WDN7EKjTIf3NbCcz+7uZPWZmZ9fltUWkEvn5MH48dOgA7nDssfCTn8Drr6c6Mqlj8SQxvwNamNkHQEczG2lmp5jZncCyBMVxCTDV3XsCU6P1MsxsO+BKYDCwO3BlTLIzxt17AwOAvc3s0ATFJSIidcTdhxKaknUlzEv2LqFM2IUwL1n/eM9lZuPNbLGZfVJu+yFmNtvMPjOzLcqacvHMdPezgJ8Dmn1PJB2dfTYsXgz77Rf6y3z5ZaojkjpSbRITVe1fB+wHnAnsAAwEPgESlSwcDdwfLd8PDK/gmGHAS+6+3N1XAC8Bh7j7Gnd/JYp1PeFJXX6C4hIRkTrk7p+6+/Xuvi8wxN33dPfRWzGx8n3AIbEbzCyb0L/zUKAPcKKZ9TGzfmb2bLlXu+g9RwHPAc/X9rOJSIKZhf4ys2fDVVfBc8+FSTOnTk11ZFIHzN2rPyh04L8I2AsoIiQKk9z984QEYbbS3VtGywasKFmPOeb3QK67Xxut/wn40d3HxBzTMortQHf/opJrjQRGArRt23bQpEmTEvERkqqoqIi8vLxUh1GtTIkTMidWxZlYmRInZE6s+++//zR33y0Z5zazqwmjaE5nK+Yli0bXfNbdd47W9wRGu/uwaP1SAHe/Po5zPefuh1eyT+VKkijOxMuUWLcmzoZLltB54kS+OPNMinNzabRwIevatoXs7CRFuW1/n6kSb7kS72SXNwNNCM28TgNaA+PN7G53/1c8JzCz/xBqccq7PHbF3d3Mqs+stjx/DjAB+EtlCUx0/nFEAxIUFBT4kCFDanqpOldYWIjiTKxMiVVxJlamxAmZFWuyuPsVZrY90J8wL1mPaHCZrdWRzUM3A8wjNFGukJkNAY4FGlFFTYzKleRRnImXKbFudZzHHx+a46xbB336QIsWcNttoblZEmzz32caizeJ2RU42t1Xmtnu7r53VDtTCMSVxLj7gZXtM7NFZtbe3ReYWXtgcQWHzQeGxKznR9cvMQ6Y6+63xROPiIikl3Sbl8zdCylbzohIpmjYEK67Di66CH76UzjuOLjpJujWLdWRSYLEO1zlzTHHLjWzscCpwLoExTE5Oh/Rz6crOGYKcLCZtYo69B8cbcPMrgVaECZKExGRzJTsecnmA51i1vOjbSKyrTGDE04I88tccw08/3yYX+ajj1IdmSRIXEmMuz/r7suj1eOBD4A84KQExXEDcFA0S/OB0TpmtpuZ3RPFsBy4Bng/el3t7svNLJ/QJK0P8KGZTTezMxIUl4iI1J1kz0v2PtDTzLqZWUPgBMJDtFozsyPNbFxRUVEiTiciidKkCfzxj2F+mUsvhV13Dds/+QQ2bUptbFIr8TYnKxWNAPZwIoNw92XA0Aq2fwCcEbM+Hhhf7ph5gCUyHhERSYn/mNkod7+DmHnJgJvNrKad+icQmiC3MbN5wJXufm8079kUIBsY7+4zEhG4uz8DPFNQUFCbPjsi9dpht7/OpwtWbd7wwnMA9GnfnOfP37d2J+/YEUaPDsvLl8M++0DXrqG/zDbWV6S+0OzHIiKSLhI2L5m7n+ju7d29gbvnu/u90fbn3b2Xu+8YTR8gImliYOeWNMgu+1y6QbYxsEuFc6BvvVat4B//gBUrYP/9w4SZnydkwF2pQ0piREQkLdTRvGRJoeZkIrV33tCeZFnZJCbbjPOG9kjshcxgxIjQX+baa+HFF8NIZt98k9jrSFIpiRERkbQRdeC/EDgb6AcsAV5095WpjKs67v6Mu4/MlHkYRNJRu+a5HD8ov7Q2pkG2cdxunWjXLDc5F2zcGC6/PPSXufVW6Nw5bH/rLfWXyQBKYkREJJ3cDHQhzEs2j83zkp2S0qhEpE7E1sYkpRamIh06wDnnhOXPPw9zygwaBK+8kvxry1ZTEiMiIulkV+D37v5fYHd3/z1hSP1zUxuWiNSFktoYg+TWwlSme3eYMAFWroQDDlB/mTSmJEZERNJJsuclE5E0d97QnvRslVU3tTDlmcHxx8PMmWGyzBdfhAED4Pvv6z4WqZKSGBERSRt1MC9ZUqhjv0jitGuey2WDG9d9LUysxo3hsstg7lwYPx5atAjbn3tO/WXShJIYERFJS+6+3t0fdvex7v5dquOpijr2i2yj2reH444Ly2+/DUccAQMHwssvpzYuURIjIiIiIlKtPfaARx+FVatg6FAYPpzG8+alOqp6S0mMiIiIiEh1zEKtzMyZcP31MHUq/S+4ADZsSHVk9ZKSGBERkVpSnxiReiQ3Fy65BObOZebll0ODBrBxIzz0UPgpdUJJjIiISC2pT4xIPbTDDqzs3z8sT54Mp5wSRjKbOjWlYdUXSmJERERERGrjmGPgscegqAgOPBCOPjqMbCZJoyRGRERERKQ2zOBnPwv9ZW64IYxe9vOfg3uqI9tmKYkREREREUmE3Fy4+OJQC3PffSG5WbUK7r5b/WUSTEmMiIiIiEgi7bAD7LprWH7oIRg5Evr3h5deSmlY2xIlMSIiIrWk0clEpFJnnQWPPw5r1sDBB8NRR8GcOamOKuMpiREREakljU4mIpUyg2OPDf1lbrwRCgvhd79LdVQZT0mMiIiIiEiyNWoEF10U+svccUfY9tVXcNdd6i+zFZTEiIiIiIjUle23h65dw/KDD8K554b+My++mNKwMo2SGBERERGRVPjjH+HJJ2HdOhg2DI44AmbPTnVUGSEn1QGIiIiIiNRLZjB8OBx6KPz1r3DNNXD77aGJWS0ddvvrfLpg1eYNLzwHQJ/2zXn+/H1rff5UU02MiIiIiEgqNWoEv/996C9zzTVh2zvvwJ13bnV/mYGdW9Ig28psa5BtDOzSqrbRpgUlMSIiIrWkIZZFJCHatYPWrcPyxIkwalToLzNlSo1Pdd7QnmRZ2SQm24zzhvZIRKQppyRGRESkljTEsogk3K23wlNPhf4yhxwChx8Os2bF/fZ2zXM5flB+aW1Mg2zjuN060a5ZbpICrltKYkRERERE0o0ZHH00zJgBY8bAG2/A5Mk1OkVsbcy2VAsDSmJERERERNJXo0Zw4YXw2Wdw/vlh2xNPhIEANmyo8q0ltTEG21QtDKRJEmNm25nZS2Y2N/pZYY8jMzs1OmaumZ1awf7JZvZJ8iMWEREREalDbduGhAZCjcx558Euu8C//13l284b2pOerbK2qVoYSJMkBrgEmOruPYGp0XoZZrYdcCUwGNgduDI22TGzYwH1qBQRERGRbds//xkSmU2b4LDDwquS/jLtmudy2eDG21QtDKRPEnM0cH+0fD8wvIJjhgEvuftyd18BvAQcAmBmecDvgGuTH6qIiIiISAqZwZFHwiefwC23wFtvwccfpzqqOpUuk11u7+4LouWFwPYVHNMR+DZmfV60DeAa4BZgTdIiFBERERFJJw0bwu9+B6edBq2iBkp//SsUF8M550CDBikNL5nqLIkxs/8AO1Sw6/LYFXd3M/ManLc/sKO7X2BmXeM4fiQwEqBt27YUFhbGe6mUKSoqUpwJlimxKs7EypQ4IbNiFRGRFNtuu/DTHV55BZ58Ev72Nxg7Fg49NLWxJUmdJTHufmBl+8xskZm1d/cFZtYeWFzBYfOBITHr+UAhsCewm5l9Rfg87cys0N2HUAF3HweMAygoKPAhQyo8LK0UFhaiOBMrU2JVnImVKXFCZsUqYbJL4MgOHTqkOhQRqc/M4PHH4bnnQg3N4YfDsGE0PumkVEeWcOnSJ2YyUDLa2KnA0xUcMwU42MxaRR36DwamuPvf3L2Du3cF9gHmVJbAiIiIJIMmuxSRtGEGRxwR+suMHQvvvUfOmm2vx0W6JDE3AAeZ2VzgwGgdM9vNzO4BcPflhL4v70evq6NtIiIiIiISq2FDuOAC+PZbVvfunepoEi4tOva7+zJgaAXbPwDOiFkfD4yv4jxfATsnIUQRERERkczTtGmqI0iKdKmJERERERERiYuSGBERERERyShKYkREREREJKMoiRERERERkYyiJEZERERERDKKkhgREREREckoSmJERERERCSjKIkREREREZGMoiRGREREREQyipIYERGRWjKzI81sXFFRUapDERGpF5TEiIiI1JK7P+PuI/Py8lIdiohIvaAkRkREREREMoqSGBERERERyShKYkREREREJKMoiRERERERkYyiJEZERERERDKKkhgREREREckoSmJERERERCSjKIkREREREZGMoiRGREREREQyipIYERERERHJKEpiREREREQkoyiJERERERGRjKIkRkREREREMoqSGBERERERyShKYkREREREJKMoiRERERERkYyiJEZERERERDJKWiQxZradmb1kZnOjn60qOe7U6Ji5ZnZqzPaGZjbOzOaY2Swz+1ndRS8iItsqM2tqZh+Y2RGpjkVERDZLiyQGuASY6u49ganRehlmth1wJTAY2B24MibZuRxY7O69gD7Aq3UStYiIpCUzG29mi83sk3LbDzGz2Wb2mZltUdZU4GJgUnKiFBGRrZWT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\n",
"text/plain": [
"<Figure size 960x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"grad = np.array(grad_val)\n",
"means = np.array(means)\n",
"variances = np.array(variances)\n",
"n = np.array(selected_qubit)\n",
"print(\"We then draw the statistical results of this sampled gradient:\")\n",
"fig = plt.figure(figsize=plt.figaspect(0.3))\n",
"\n",
"\n",
"# ============= The first figure =============\n",
"# Calculate the relationship between the average gradient of random sampling and the number of qubits\n",
"plt.subplot(1, 2, 1)\n",
"plt.plot(n, means, \"o-.\")\n",
"plt.xlabel(r\"Qubit #\")\n",
"plt.ylabel(r\"$ \\partial \\theta_{i} \\langle 0|H |0\\rangle$ Mean\")\n",
"plt.title(\"Mean of {} sampled graident\".format(samples))\n",
"plt.xlim([1,9])\n",
"plt.ylim([-0.06, 0.06])\n",
"plt.grid()\n",
"\n",
"# ============= The second figure =============\n",
"# Calculate the relationship between the variance of the randomly sampled gradient and the number of qubits\n",
"plt.subplot(1, 2, 2)\n",
"plt.semilogy(n, variances, \"v\")\n",
"\n",
"# Polynomial fitting\n",
"fit = np.polyfit(n, np.log(variances), 1)\n",
"slope = fit[0] \n",
"intercept = fit[1] \n",
"plt.semilogy(n, np.exp(n*slope + intercept), \"r--\", label=\"Slope {:03.4f}\".format(slope))\n",
"plt.xlabel(r\"Qubit #\")\n",
"plt.ylabel(r\"$ \\partial \\theta_{i} \\langle 0|H |0\\rangle$ Variance\")\n",
"plt.title(\"Variance of {} sampled graident\".format(samples))\n",
"plt.legend()\n",
"plt.xlim([1,9])\n",
"plt.ylim([0.0001, 0.1])\n",
"plt.grid()\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It should be noted that, in theory, only when the network structure and loss function we choose meet certain conditions (unitary 2-design), see paper [[1]](https://arxiv.org/abs/1803.11173), this effect will appear. Then we might as well visualize the influence of choosing different qubits on the optimization landscape:\n",
"\n",
"![BP-fig-qubit_landscape_compare](./figures/BP-fig-qubit_landscape_compare.png \"(a) Optimization landscape sampled for 2,4,and 6 qubits from left to right in different z-axis scale. (b) Same landscape in a fixed z-axis scale.\")\n",
"<div style=\"text-align:center\">(a) Optimization landscape sampled for 2,4,and 6 qubits from left to right in different z-axis scale. (b) Same landscape in a fixed z-axis scale. </div>\n",
"\n",
"\n",
"$\\theta_1$ and $\\theta_2$ are the first two circuit parameters, and the remaining parameters are all fixed to $\\pi$. This way, it helps us visualize the shape of this high-dimensional manifold. Unsurprisingly, the landscape becomes more flat as $n$ increases. **Notice the rapidly decreasing scale in the $z$-axis**. Compared with the 2-qubit case, the optimized landscape of 6 qubits is very flat."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_______\n",
"\n",
"## References\n",
"\n",
"[1] McClean, J. R., Boixo, S., Smelyanskiy, V. N., Babbush, R. & Neven, H. Barren plateaus in quantum neural network training landscapes. [Nat. Commun. 9, 4812 (2018).](https://www.nature.com/articles/s41467-018-07090-4)\n",
"\n",
"[2] Cerezo, M., Sone, A., Volkoff, T., Cincio, L. & Coles, P. J. Cost-Function-Dependent Barren Plateaus in Shallow Quantum Neural Networks. [arXiv:2001.00550 (2020).](https://arxiv.org/abs/2001.00550)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_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_minor": 4
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 大规模量子近似优化分治算法\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 概览\n",
"\n",
"[量子近似优化算法](./QAOA_CN.ipynb)(quantum approximate optimization algorithm, QAOA)是一个将量子与经典结合起来,用于解决组合优化问题的算法。但是,由于现阶段量子比特数量的限制,该算法无法处理大规模问题,且该算法的运行时间随着问题规模的增大,成指数增长。关于量子近似优化算法更详细的讨论见 [1]。\n",
"\n",
"分治法(divide-and-conquer, DC)是可以解决上述瓶颈的一种方法。主要是将一个大问题拆分若干个相似的子问题,将这些子问题解决之后再将子问题合并,从而得到母问题的解。Junde Li 等人在2021年提出量子近似优化的分治算法 [2] 将上述技术应用于解决较大规模的最大割问题。本教程所使用的方法在该论文的基础之上做出了一些改进。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 具体算法"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 大图分割\n",
"\n",
"在图论中,我们用一个图形的边 $E$ 和顶点 $V$ 定义一个图形 $G=(V,E)$。假设它有 $|V| = n$ 个顶点,但是含噪中型量子(noisy intermediate-scale quantum, NISQ)设备上最多可以运行 $k$ 个量子比特($n > k$)。这种情况下,我们使用``大图分割 LGP``的方法将图形 $G$ 拆分两个子图 $G_0$ 和 $G_1$。为了防止遗漏任意一条边,在拆分的时候至少有一个点被两个子图共同拥有。我们把这些共有的顶点叫做分离顶点(集合),并且约束这个集合的大小小于 $k$。以下的代码定义了如何进行大图分割。"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-16T03:41:44.449329Z",
"start_time": "2021-05-16T03:41:43.034272Z"
}
},
"outputs": [],
"source": [
"import networkx as nx # networkx的版本 >= 2.5\n",
"import matplotlib.pyplot as plt\n",
"from itertools import combinations\n",
"\n",
"# 将一个图形分割成两个有重合的分离顶点子图\n",
"def NaiveLGP(g, k):\n",
" E = list(g.edges)\n",
" E = [(min([u, v]),max([u, v])) for (u, v) in E]\n",
" E.sort(key=lambda tup:tup[0])\n",
" V = list(g.nodes)\n",
" V.sort()\n",
"\n",
" counter = 1\n",
" while counter < k:\n",
" num_nodes = counter\n",
" nodes_combo = list(combinations(V, num_nodes))\n",
" # 找有效的分离顶点\n",
" for p in nodes_combo:\n",
" V1 = [x for x in V if x not in p]\n",
" E1 = [e for e in g.edges if e not in g.edges(p)]\n",
" G1 = nx.Graph()\n",
" G1.add_nodes_from(V1)\n",
" G1.add_edges_from(E1)\n",
" S = [G1.subgraph(c).copy() for c in nx.connected_components(G1)]\n",
" if len(S) == 2:\n",
" # 将分离顶点加入不相连的子图中\n",
" V_S0 = list(S[0].nodes)\n",
" E_S0 = list(S[0].edges) \n",
" V_S1 = list(S[1].nodes)\n",
" E_S1 = list(S[1].edges)\n",
" for (u, v) in g.edges(p):\n",
" if u in V_S0 or v in V_S0:\n",
" S[0].add_edges_from([(u, v)])\n",
" if u in V_S1 or v in V_S1:\n",
" S[1].add_edges_from([(u, v)])\n",
" if u in p and v in p:\n",
" S[0].add_edges_from([(u, v)])\n",
" S[1].add_edges_from([(u, v)])\n",
"\n",
" return S\n",
"\n",
" counter += 1\n",
" print(\"G的连接度大于k\")\n",
"\n",
" return {}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"我们给了以下的例子去说明``大图分割``是如何进行的。假设一个随机图形有10个顶点,但是 NISQ 设备最多支持9个量子比特,即 $k=9$。那么根据``大图分割``,红色的顶点0和2将被选为分离顶点。首先将这些分离顶点去掉,剩下的图将是一个不连接图形并可以被分成两个子图,比如下图中的顶点3-9和顶点1。随后,我们再将这些分离顶点和相关边分别加回两个子图中,从而保证所有的边都不会被遗漏。"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-16T03:41:44.839484Z",
"start_time": "2021-05-16T03:41:44.455664Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 1080x288 with 3 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# 生成一个有 10 个顶点的图形\n",
"n = 10\n",
"G = nx.Graph()\n",
"G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])\n",
"G.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5),\n",
" (5, 6), (6, 7), (7, 8), (8, 9), (9, 0)])\n",
" \n",
"k = 9 # 设定量子比特的最大数量\n",
"S = NaiveLGP(G,k) # 利用大图分割对图形 G 进行分割\n",
"sep_node = list(set(S[0].nodes).intersection(set(S[1].nodes))) # 找到分离顶点\n",
"\n",
"# 图形示例\n",
"options = {\n",
" \"with_labels\": True,\n",
" \"font_color\": \"white\"\n",
"}\n",
"node_color1 = [\"red\" if i in sep_node else \"blue\" for i in range(n)]\n",
"node_color2 = [\"red\" if list(S[0].nodes)[i] in sep_node else \"blue\" for i in range(len(S[0].nodes))]\n",
"node_color3 = [\"red\" if list(S[1].nodes)[i] in sep_node else \"blue\" for i in range(len(S[1].nodes))]\n",
"\n",
"fig, ax = plt.subplots(1, 3, figsize=(15, 4))\n",
"for i, a in enumerate(ax):\n",
" a.axis('off')\n",
" a.margins(0.20)\n",
"nx.draw_networkx(G, pos=nx.circular_layout(G), ax=ax[0], **options, node_color=node_color1)\n",
"nx.draw_networkx(S[0], pos=nx.circular_layout(S[0]), ax=ax[1], **options, node_color=node_color2)\n",
"nx.draw_networkx(S[1], pos=nx.circular_layout(S[1]), ax=ax[2], **options, node_color=node_color3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"值得提醒的一点是,我们的例子中 $k=9$,``大图分割``得到的两个子图的顶点数都小于或等于 $k$,那么两个子图的最大割问题可以直接被``量子近似优化算法``解决。但如果得到的子图的顶点数依然大于 $k$,那我们将对子图重复之前的做法,直至所有的子图顶点都小于或等于 $k$。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 图形重构\n",
"\n",
"当``量子近似优化(分治)算法``被应用到分离的子图上之后,所有的顶点会被分成两个部分,即 $S_0$ 和 $S_1$。我们需要将子图的最大割进行整合,得到母图的最大割。因为两个子图有共同的顶点,即分离顶点,我们要确保它们所在的最大割集合吻合,即 $S_0$ 还是 $S_1$ 需要吻合。比如,如果对于一个子图来说,分离顶点在它的最大割当中所在的分割集合都是 $S_0$,而另一个子图的最大割中,分离顶点们在的分割集合是 $S_1$,那么相应的两个最大割将不能被整合。所以为了解决这一问题,对于每个子图,我们将提供多个可能的最大割,从而在这些可能的最大割当中寻找可以整合的且可能性最高的进行整合,从而得到母图的最大割。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-16T03:41:46.108438Z",
"start_time": "2021-05-16T03:41:45.970323Z"
}
},
"outputs": [],
"source": [
"def GR(str_cnt1, str_cnt2):\n",
" com_cnt = []\n",
" n = len(str_cnt1[0][0])\n",
" com_index = []\n",
" for i in range(n):\n",
" if str_cnt1[0][0][i] != \"x\" and str_cnt2[0][0][i] != \"x\":\n",
" com_index.append(i)\n",
"\n",
" for (str1, cnt1) in str_cnt1:\n",
" for (str2, cnt2) in str_cnt2: \n",
" # 检查分离顶点在两个子图所在的集合是否一致\n",
" validity = [str1[i] == str2[i] for i in com_index]\n",
" if False not in validity:\n",
" com_str = [[0]] * n\n",
" for i in range(n):\n",
" if str1[i] != \"x\":\n",
" com_str[i] = str(str1[i])\n",
" else:\n",
" com_str[i] = str(str2[i])\n",
" com_cnt.append((\"\".join(com_str), min(cnt1, cnt2)))\n",
"\n",
" # 将{最大割:频率}按频率从大到小排列\n",
" com_cnt.sort(key=lambda tup:tup[1])\n",
" return com_cnt[::-1]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"我们将延续上述10个顶点的圆的例子对``图形重构(graph reconstruction, GR)``进行说明。对于所分得的两个子图,我们先用``量子近似优化算法``求解最大割,再用``图形重构``将子图的最大割整合,得到原图的最大割。下面所给的代码实现了这一步骤。代码中的参数 $t$,代表想要保留最有可能的最大割的数量。如果 $t$ 大于 $2^n$,那么所有可能的最大割,即所有可能的顶点分类,都将被保留用于整合。"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-16T03:42:41.303385Z",
"start_time": "2021-05-16T03:41:47.071053Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"第一个子图的最大割:\n",
"{'010xxxxxxx': 0.49999449162430293, '101xxxxxxx': 0.49999449162430293, '000xxxxxxx': 2.4202658690211183e-06, '111xxxxxxx': 2.420265869021086e-06, '110xxxxxxx': 1.544054913842632e-06, '011xxxxxxx': 1.5440549138425979e-06, '001xxxxxxx': 1.5440549138425754e-06, '100xxxxxxx': 1.5440549138424998e-06}\n",
"第二个子图的最大割:\n",
"{'0x01010101': 0.14011845299520287, '1x10101010': 0.1401184529952028, '1x01010010': 0.04249785377879272, '0x10100101': 0.04249785377879272, '1x01011010': 0.0424978537787927, '0x10101101': 0.0424978537787927, '0x10101001': 0.036328002709709005, '1x01001010': 0.036328002709709, '0x10110101': 0.036328002709709, '1x01010110': 0.03632800270970896}\n",
"母图的最大割:\n",
"{'0101010101': 0.14011845299520287, '1010101010': 0.1401184529952028, '0001010101': 2.4202658690211183e-06, '1110101010': 2.420265869021086e-06, '1101010110': 1.544054913842632e-06, '1101001010': 1.544054913842632e-06, '1101011010': 1.544054913842632e-06, '1101010010': 1.544054913842632e-06, '0110110101': 1.5440549138425979e-06, '0110101001': 1.5440549138425979e-06}\n"
]
}
],
"source": [
"# 我们利用 量子近似优化算法 计算上面例子两个子图的最大割\n",
"# 在下一小章中,我们将使用 量子近似优化分治算法 计算子图的最大割,因为子图顶点数量有可能超过量子比特的限制。\n",
"import paddle\n",
"from paddle_quantum.QAOA.maxcut import find_cut\n",
"\n",
"# 设定 量子近似优化算法 中的参数\n",
"p = 3 # 量子电路的层数\n",
"ITR = 100 # 训练迭代的次数\n",
"LR = 0.5 # 基于梯度下降的优化方法的学习率\n",
"# 设定 图形重构 中的参数\n",
"t = 10 # 想要保留最有可能的最大割的数量\n",
"paddle.seed(999) # 固定随机种子\n",
"\n",
"# 图形重构完整过程\n",
"S_str_cnt = []\n",
"for si in S:\n",
" siv = list(si.nodes)\n",
" \n",
" # 计算子图的最大割\n",
" tmp, si_str_cnt_relabeled = find_cut(si, p, ITR, LR)\n",
" \n",
" # 填充子图的最大割结果,使它们和原图的顶点数量和顺序吻合\n",
" si_str_cnt = []\n",
" for str_relabeled in si_str_cnt_relabeled:\n",
" strr = \"\"\n",
" for i in range(len(G.nodes)):\n",
" if i in siv:\n",
" strr += str_relabeled[siv.index(i)]\n",
" else:\n",
" strr += \"x\"\n",
" si_str_cnt.append((strr, si_str_cnt_relabeled[str_relabeled]))\n",
" si_str_cnt.sort(key=lambda tup:tup[1])\n",
" S_str_cnt.append(si_str_cnt[::-1][:t])\n",
"\n",
"# 当子图的最大割被找到之后,我们开始图形重构这一步\n",
"print(\"第一个子图的最大割:\\n\" + str(dict(S_str_cnt[0])))\n",
"print(\"第二个子图的最大割:\\n\" + str(dict(S_str_cnt[1])))\n",
"out_cnt = GR(S_str_cnt[0], S_str_cnt[1])\n",
"print(\"母图的最大割:\\n\" + str(dict(out_cnt[:t])))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"就以上例子来说,对于第一个子图而言,最有可能的几个最大割将包括 {'010xxxxxxx','101xxxxxxx'},而第二个子图最有可能的最大割将包括 {'1x10101010','0x01010101'}。这些字符串中的 'x' 代表不在这个子图却在母图的顶点。从这个例子中我们看到,分离顶点0和2在第一个子图中可能的最大割,'010xxxxxxx',中都属于 $S_0$,但它们在第二个子图的最大割,'1x10101010',中都属于 $S_1$,所以它们无法整合。(虽然因为 $S_0$ 和 $S_1$ 的对称性,我们可以把他们进行反转从而进行整合,但是没有必要这么做。)\n",
"\n",
"我们接着尝试整合第一个子图的第一个最大割 '010xxxxxxx' 和第二个子图的第二个最大割 '0x01010101',此最大割即是'101xxxxxxx' 的对称组。我们发现在这两个字符串所代表的最大割当中,分离顶点0和2都属于 $S_0$,我们也可以从下图第一张和第二张图中看出。所以我们可以整合这两个最大割并得到母图的最大割,'0101010101',如下图第三张图所示。\n",
"\n",
"以下为图形展示,前两个图为两个子图的最大割实例,最右的图为母图的最大割。红色点和蓝色点分别表示被分在在 $S_0$ 和 $S_1$ 中的顶点,虚线表示被切割的边。"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-16T03:42:41.647686Z",
"start_time": "2021-05-16T03:42:41.309407Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 1080x288 with 3 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# 计算出的两个子图的最大割\n",
"strr1 = '010xxxxxxx'\n",
"strr2 = '0x01010101' \n",
"strr = '0101010101'\n",
"\n",
"# 图形示例展示\n",
"options0 = {\n",
" \"node_color\": [\"red\" if strr1[i] == '0' else \"blue\" for i in S[0].nodes],\n",
" \"style\": [\"solid\" if strr1[u] == strr1[v] else \"dashed\" for (u, v) in list(S[0].edges)]\n",
"}\n",
"options1 = {\n",
" \"node_color\": [\"red\" if strr2[i] == '0' else \"blue\" for i in S[1].nodes],\n",
" \"style\": [\"solid\" if strr2[u] == strr2[v] else \"dashed\" for (u, v) in list(S[1].edges)]\n",
"}\n",
"options2 = {\n",
" \"node_color\": [\"red\" if strr[i] == '0' else \"blue\" for i in range(n)],\n",
" \"style\": [\"solid\" if strr[u] == strr[v] else \"dashed\" for (u, v) in list(G.edges)]\n",
"}\n",
"\n",
"fig, ax = plt.subplots(1, 3, figsize=(15,4))\n",
"for i, a in enumerate(ax):\n",
" a.axis('off')\n",
" a.margins(0.20)\n",
"nx.draw_networkx(S[0], pos=nx.circular_layout(S[0]), ax=ax[0], **options, **options0)\n",
"nx.draw_networkx(S[1], pos=nx.circular_layout(S[1]), ax=ax[1], **options, **options1)\n",
"nx.draw_networkx(G, pos=nx.circular_layout(G), ax=ax[2], **options, **options2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 量子近似优化分治法\n",
"\n",
"为了找到一个大图 $G$ 的最大割,我们采用``量子近似优化分治法``。这个方法像上面描述的一样,先递归性地利用``大图分割``分割图形,再利用``图形重构``递归性地整合两个子图的最大割。\n",
"\n",
"首先如果输入图形的顶点数大于量子比特数量限制 $k$,它将被``大图分割``分成两个子图。反之,可以直接求解它的最大割(不用拆分)。每一个子图将递归性地被输入进``量子近似优化分治法``,直到它的最大割被返回。最大割被返回说明在某一步,它某些递归的子图的顶点数量小于$k$,直接被``量子近似优化分治法``解得,再一层一层地经历``图形重构``,直到返回这个子图所在层。\n",
"\n",
"下面是利用``图形重构``和``大图分割``完成的``量子近似优化分治法``的代码。``量子近似优化分治法``将返回最有可能的最大割和前 $t$ 个最有可能的最大割。"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-16T03:44:13.784486Z",
"start_time": "2021-05-16T03:42:41.653981Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"最有可能的 t 个图形 G 的最大割: {'0101010101': 947, '1010101010': 920, '1001010010': 150, '1001010100': 150, '1001010110': 150, '1101010010': 136, '1101010100': 136, '1101010110': 136, '1101010101': 135, '1001010101': 135}\n",
"量子近似优化分治算法找到的图形 G 的(最有可能的)最大割: 0101010101\n"
]
}
],
"source": [
"def DC_QAOA(g, p, t, s, k, ITR, LR):\n",
" if len(g.nodes) > k:\n",
" # 利用 大图分割 得到两个子图\n",
" S = NaiveLGP(g, k)\n",
"\n",
" S_str_cnt = []\n",
" for si in S:\n",
" siv = list(si.nodes)\n",
" # 递归性地计算子图的最大割\n",
" _, si_str_cnt_relabeled = DC_QAOA(si, p, t, s, k, ITR, LR)\n",
" # 填充子图的最大割结果,使其和母图的顶点吻合\n",
" si_str_cnt = []\n",
" for str_relabeled in si_str_cnt_relabeled:\n",
" strr = \"\"\n",
" for v in g.nodes:\n",
" if v in siv:\n",
" strr += str_relabeled[siv.index(v)]\n",
" else:\n",
" strr += \"x\" \n",
" si_str_cnt.append((strr, si_str_cnt_relabeled[str_relabeled]))\n",
" si_str_cnt.sort(key = lambda tup:tup[1])\n",
" S_str_cnt.append(si_str_cnt[::-1][:t])\n",
"\n",
" # 利用 图形重构 整合子图最大割\n",
" out_cnt = GR(S_str_cnt[0], S_str_cnt[1])\n",
" else:\n",
" if len(g.nodes) == 1:\n",
" return [(\"0\", 99999), (\"1\", 99999)]\n",
" _, out_cnt = find_cut(g, p, ITR, LR, shots=3000)\n",
" # 将词典格式转成列表格式,易于排序\n",
" out_cnt = [(k, v) for k, v in out_cnt.items()]\n",
" # 将{最大割:频率}按频率从大到小排列\n",
" out_cnt.sort(key=lambda tup:tup[1])\n",
" out_cnt = out_cnt[::-1]\n",
"\n",
" # 只保留最有可能的t个最大割\n",
" out_cnt = out_cnt[:t]\n",
" # 等比例调节频率的显示\n",
" cnt_sum = sum(cnt for (str,cnt) in out_cnt)\n",
" out_cnt = [(k, int(s * v / cnt_sum)) for (k, v) in out_cnt]\n",
"\n",
" return out_cnt[0][0], dict(out_cnt)\n",
" \n",
"# 设定 量子近似优化算法 中的参数\n",
"p = 2 # 量子电路的层数\n",
"ITR = 100 # 训练迭代的次数\n",
"LR = 0.5 # 基于梯度下降的优化方法的学习率\n",
"\n",
"# 设定 量子近似优化分治算法 中的参数\n",
"s = 3000 # 等比例调节频率的比例\n",
"t = 10 # 想要保留最有可能的最大割的数量\n",
"k = 5 # 量子比特的数量限制\n",
"\n",
"# 量子近似优化分治算法使用\n",
"max_cut, out_cnt = DC_QAOA(G, p, t, s, k, ITR, LR)\n",
"print(\"最有可能的 t 个图形 G 的最大割: \" + str(out_cnt))\n",
"print(\"量子近似优化分治算法找到的图形 G 的(最有可能的)最大割: \" + str(max_cut))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 应用范围\n",
"\n",
"**以上表述的``量子近似优化分治法``可以估计一个图形的最大割,当且仅当,它和它递归出来的顶点数量大于 $k$,且子图的伪连接度(pseudo-connectivity)都小于 $k$**。伪连接度的定义为:一个连接图变成不连接的两个子图所需要移除的最小的顶点数量。\n",
"\n",
"当 $k > 1$ 的时候,圆圈就是一个例子。因为只需要移除两个点,圆圈就会被拆成两条不相连的子图,所以所有圆圈的伪连接度都是2。我们拿六个顶点的圆 $C_6$ 并且 $k=4$ 举例。``大图分割``会将它分成 $P_5$(顶点数量为5的子图)和 $P_2$,$P_2$ 的顶点数量在 $k$ 之下,可以直接使用``近似优化算法``计算。而子图 $P_5$ 是一个链状结构,他的伪连接度是 $1 < k$。所以``大图分割``将继续分割 $P_5$,并把它分成了 $P'_4$ 和 $P'_2$。新的子图的顶点数量都小于或等于 $k$,我们都不再需要考虑他们伪连接度。\n",
"\n",
"``量子近似优化分治法``不可解的图包括顶点数量大于 $k$ 的完全图(complete graph)。对于完全图来说,无论怎么移除顶点,剩余的图都是连接图。有些图是否适用决定于 $k$ 的大小,我们以下给了个这样的例子。\n",
"\n",
"最左的图就是实例图,这个图的伪连接度是2。如果 $k=2$,那么分离点的数量只能为1个,如果分离点是4,那么这个图被拆分成三部分而不是两部分(下图中间所示);如果分离点是其他的几个,这个图仍然连在一起,没有被拆开。此外,该图的伪连接度为2并不小于 $k$,不满足条件,所以``量子近似优化分治法``并不适用于这个例子。但如果 $k=3$,伪连接度是 $2 < k$,这个图可以进行拆分成两个子图,其中一个的顶点数量小于等于 $k$,另一个的伪连接度显而易见是 $1<k$(移除顶点4)。``量子近似优化分治法``在这种情况下可以解决这个图。于是我们移除顶点0和4(如下图最右所示),剩下的图将是两个不相连的子图。我们再将分离顶点0和4加回去,并在这两个子图上计算最大割。``量子近似优化分治法``最终可以成功给出最大割。\n",
"\n",
"![limitations-connectivity](./figures/dcqaoa-fig-applicability_example.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"读者可以在以下代码中自己调试 $k$,利用``量子近似优化分治法``试验上述的示例图的最大割,从而感受这个方法的适用范围。"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-16T03:44:54.150187Z",
"start_time": "2021-05-16T03:44:13.788802Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"最有可能的 t 个图形 G 的最大割:{'00101': 549, '10110': 512, '00001': 510, '11110': 501, '01001': 471, '11010': 457}\n"
]
}
],
"source": [
"G = nx.Graph()\n",
"G.add_nodes_from([0, 1, 2, 3, 4])\n",
"G.add_edges_from([(0, 4), (1, 2), (1, 4), (2, 4), (3, 4)])\n",
"k = 3\n",
"_, out_cnt = DC_QAOA(G, p, t, s, k, ITR, LR)\n",
"print(\"最有可能的 t 个图形 G 的最大割:\" + str(dict(out_cnt)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 算法测试效果\n",
"\n",
"下面,我们比较量子近似优化分治法所得到的最大割和半正定规划(SDP)方法得到的理论上界进行比较。这里,我们用的例子是10个顶点的随机图,量子比特数量限制 $k=5$。\n",
"\n",
"为了能正确运行以下测试代码,用户首先应该安装 cvxpy:`pip install cvxpy`。**Windows 如果直接使用 pip 安装,在运行时可能会出现报错,建议新建 conda 环境后使用 conda 安装 cvxpy。**更多详情请参考 [https://www.cvxpy.org/install/](https://www.cvxpy.org/install/)。"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T07:06:44.690385Z",
"start_time": "2021-05-11T07:06:44.433742Z"
}
},
"outputs": [],
"source": [
"import cvxpy as cvx\n",
"import networkx as nx\n",
"\n",
"def sdp_solver(G):\n",
" \"\"\"\n",
" 通过半正定规划 SDP 来找到最大割问题的理论上界。\n",
" \"\"\"\n",
" n = len(G)\n",
" adj_mat = nx.adjacency_matrix(G).toarray()\n",
" Y = cvx.Variable((n, n), PSD=True)\n",
" cut_size = 0.25 * cvx.sum(cvx.multiply(adj_mat, 1 - Y))\n",
" problem = cvx.Problem(cvx.Maximize(cut_size), [cvx.diag(Y) == 1])\n",
" opt_val = problem.solve(cvx.SCS)\n",
"\n",
" return opt_val"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T07:16:56.698522Z",
"start_time": "2021-05-11T07:06:44.697731Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"顶点数量 = 10\n",
"顶点编号 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
"\n",
"随机图形 1\n",
"边 = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (2, 3), (2, 4), (2, 7), (3, 8), (3, 9), (4, 5), (5, 6), (5, 9), (6, 7), (6, 8)]\n",
"半正定规划找的最大割的上限: 14.773421849579332\n",
"量子近似优化分治算法找到的最大割分类: 0011011000, 最大割 = 14.0\n",
"\n",
"随机图形 2\n",
"边 = [(0, 1), (0, 2), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (1, 4), (1, 6), (1, 7), (1, 8), (2, 4), (2, 5), (2, 7), (2, 9), (3, 6), (3, 8), (3, 9), (4, 5), (4, 6), (5, 7), (6, 9), (7, 9)]\n",
"半正定规划找的最大割的上限: 17.637249299053625\n",
"量子近似优化分治算法找到的最大割分类: 1010011010, 最大割 = 15.0\n",
"\n",
"随机图形 3\n",
"边 = [(0, 1), (0, 2), (0, 4), (0, 5), (0, 7), (0, 8), (0, 9), (1, 4), (1, 5), (2, 7), (2, 8), (2, 9), (3, 5), (3, 6), (3, 8), (3, 9), (4, 5), (4, 6), (4, 9), (5, 6), (5, 8), (5, 9), (6, 7), (7, 8), (7, 9)]\n",
"半正定规划找的最大割的上限: 19.048588813917966\n",
"量子近似优化分治算法找到的最大割分类: 0010110100, 最大割 = 17.0\n",
"\n",
"随机图形 4\n",
"边 = [(0, 3), (0, 6), (0, 7), (0, 8), (0, 9), (1, 2), (1, 5), (1, 7), (2, 6), (2, 7), (3, 4), (3, 7), (3, 8), (3, 9), (4, 5), (4, 8), (4, 9), (5, 6), (5, 9), (6, 7), (7, 9), (8, 9)]\n",
"半正定规划找的最大割的上限: 16.551132643953018\n",
"量子近似优化分治算法找到的最大割分类: 1010110100, 最大割 = 16.0\n",
"\n",
"随机图形 5\n",
"边 = [(0, 2), (0, 5), (0, 6), (0, 7), (0, 8), (1, 2), (1, 4), (1, 7), (2, 4), (2, 7), (2, 9), (3, 4), (3, 5), (3, 6), (3, 9), (4, 6), (4, 7), (4, 8), (5, 6), (5, 7), (5, 9), (6, 8), (7, 8), (8, 9)]\n",
"半正定规划找的最大割的上限: 18.19997280321202\n",
"量子近似优化分治算法找到的最大割分类: 1100110001, 最大割 = 17.0\n"
]
}
],
"source": [
"n = 10\n",
"iter = 5\n",
"print(\"顶点数量 = \" + str(n))\n",
"print(\"顶点编号 = \" + str([i for i in range(n)]))\n",
"\n",
"value_dc_qaoa_ls = []\n",
"ubound_sdp_ls = []\n",
"for i in range(iter):\n",
" print(\"\\n随机图形 \" + str(i+1))\n",
" # 生成随机图形\n",
" G = nx.erdos_renyi_graph(n, 0.1, 100 * i, directed=False)\n",
" while nx.is_connected(G) == False:\n",
" G = nx.erdos_renyi_graph(n, 0.5, directed=False)\n",
" print(\"边 = \" + str(list(G.edges)))\n",
" \n",
" # 半正定规划(SDP)方法找最大割的上限\n",
" ubound_sdp = sdp_solver(G)\n",
" ubound_sdp_ls.append(ubound_sdp)\n",
" print(\"半正定规划找的最大割的上限: \" + str(ubound_sdp))\n",
"\n",
"\n",
" # 设定 量子近似优化算法 中的参数\n",
" p = 2 # 量子电路的层数\n",
" ITR = 100 # 训练迭代的次数\n",
" LR = 0.5 # 基于梯度下降的优化方法的学习率\n",
" # 设定 量子近似优化分治算法 中的参数\n",
" s = 3000 # 等比例调节频率的比例\n",
" t = 10 # 想要保留最有可能的最大割的数量\n",
" k = 5 # 量子比特的数量限制\n",
"\n",
" try:\n",
" cut_dc_qaoa, out_cnt = DC_QAOA(G, p, t, s, k, ITR, LR)\n",
" cut_dc_qaoa1 = [\"solid\" if cut_dc_qaoa[u] == cut_dc_qaoa[v] else \"dashed\" for (u, v) in list(G.edges)]\n",
" value_dc_qaoa = cut_dc_qaoa1.count(\"dashed\")\n",
" value_dc_qaoa_ls.append(value_dc_qaoa)\n",
" print(\"量子近似优化分治算法找到的最大割分类: \" + str(cut_dc_qaoa) + \", 最大割 = \" + str(float(value_dc_qaoa))) \n",
" except Exception as e:\n",
" value_dc_qaoa = 0\n",
" value_dc_qaoa_ls.append(value_dc_qaoa)\n",
" print(\"量子近似优化分治算法找最大割失败,错误信息:'\" + str(e) + \"'\")"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T07:16:56.935061Z",
"start_time": "2021-05-11T07:16:56.704158Z"
}
},
"outputs": [
{
"data": {
"image/png": "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TzoXjn983LmgXIC89NJLNGnShObNm9OyZUsWLFgAQIcOHWjQoMGZMsv33XcfCQkJZ96XXk+nadOm3HLLLZmWanZThw4dCGRX861bt9K0adM8r8cSvwlfqhA3AUa0h8NboeenTl0dNxSKgB6joGQlp5jb8YPuxBFg8+bNY8qUKSxZsoTly5fz66+/Ur36X72mPvvsM5YvX87y5cspWrTo30o3FCtWjLi4OFauXEmRIkUYMcL9Ci++1P4JBZb4TXhShW/vhcl3QZWWTnG1Ri7XXile1qn3c2wfLBnjbiwBsmfPHsqXL0/RokUBKF++PFWqVDlnuSJFivDqq6+yfft2li07d2Cb9u3bs3HjxnOmlyxZ8szzSZMmMWDAAAAGDBjAXXfdRWxsLPXr12fKlCkAjBkzhu7du9OhQwfq1avH888/f+b948aNo02bNrRs2ZI777zzTJIvWbIkjz76KC1atGDevHnnxPDpp5+eOTNZuHAhAIcOHeKGG26gefPmtGvXjuXLlwPw3HPP8dprr515b9OmTdm6dStbt26lUaNGDBkyhCZNmtC1a1dOnjwJcKY+UYsWLXj33Xez2Nu+s8RvwpOI00Wz47+cMsplqrkdkaNqaxgyAy59xJ3tf3ztuY+FI515p09kPH/pZ8784wfPnZeNrl27smPHDurXr88999zD7NmzM102IiKCFi1asHbt37u/pqSk8NNPP50pouarrVu3snDhQn744QfuuuuuM4ORL1y4kK+++orly5fz5ZdfsmjRItasWcPEiRP5448/iIuLIyIigs8+cz738ePHadu2LcuWLePSSy89ZzsnTpwgLi6O9957j0GDBgHw7LPP0qpVK5YvX87LL79Mv379so13w4YN3HvvvaxatYro6Gi++uorAAYOHMjbb7+d4Q9ibll3ThM+0tJg7ltQvj40vAYuvs/tiDJ2vieBHdoCiTvPLfMcRkqWLMnixYv5/fffmTlzJr169eKVV145c2R+Nu8SMidPnqRly5aAc8Q/ePDgHG27Z8+eFCpUiHr16lG7du0zPyhdunShXLlyANx0003MmTOHwoULs3jxYi688MIz265YsSLg/CD16NEj0+307t0bgMsuu4wjR46QkJDAnDlzziTuK664goMHD3LkSNZjIdSqVevM523dujVbt24lISGBhIQELrvsMgBuv/12fvrppxzt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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"plt.plot(value_dc_qaoa_ls, label=\"DC-QAOA\")\n",
"plt.plot(ubound_sdp_ls, label=\"SDP upper bound\", linestyle=\"--\")\n",
"plt.title('Max-Cut Performancce')\n",
"plt.xlabel('Random Graph')\n",
"plt.ylabel('Calculated Optimal Max Cut')\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"从上面的线形图中,我们可以说明``量子近似优化分治法``找到的最大割和理论上限接近。\n",
"\n",
"## 应用\n",
"\n",
"最大割问题属于应用范围很广的二次无约束二值优化(quadratic unconstrained binary optimization, QUBO)问题。此类问题的应用范围十分广泛,上至为NP-困难问题创建模型,下到找自旋玻璃的基态 [5]。同时最大割问题本身也有很广泛的应用。\n",
"\n",
"最大割问题和很多领域都有紧密的联系,比如超大规模集成电路(VLSI circuit)设计,统计物理。减少超大规模集成电路设计所用的孔和寻找自选玻璃基态都可以归约到最大割问题 [6]。更重要的是,最大割问题给很多算法或者技术提供了一个测试台。比如适用于最大割问题的半正定规划方法被后续用在了数据集合设计 [7] 和相位检索上 [8, 9]。\n",
"\n",
"更多关于最大割的应用可以在 [10-12] 里找到。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## 参考文献\n",
"\n",
"[1] Akshay, V., et al. \"Reachability deficits in quantum approximate optimization.\" [Physical Review Letters 124.9 (2020): 090504.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.124.090504)\n",
"\n",
"[2] Li, Junde, Mahabubul Alam, and Swaroop Ghosh. \"Large-scale Quantum Approximate Optimization via Divide-and-Conquer.\" [arXiv preprint arXiv:2102.13288 (2021).](https://arxiv.org/abs/2101.03717)\n",
"\n",
"[3] Goemans, Michel X., and David P. Williamson. \"Improved approximation algorithms for maximum cut and satisfiability problems using semidefinite programming.\" [Journal of the ACM (JACM) 42.6 (1995): 1115-1145.](http://www-math.mit.edu/~goemans/PAPERS/maxcut-jacm.pdf)\n",
"\n",
"[4] Burer, Samuel, and Renato DC Monteiro. \"Local minima and convergence in low-rank semidefinite programming.\" [Mathematical Programming 103.3 (2005): 427-444.](https://link.springer.com/article/10.1007/s10107-004-0564-1)\n",
"\n",
"[5] Kochenberger, Gary, et al. \"The unconstrained binary quadratic programming problem: a survey.\" [Journal of Combinatorial Optimization 28.1 (2014): 58-81.](https://link.springer.com/article/10.1007/s10878-014-9734-0)\n",
"\n",
"[6] Barahona, Francisco, et al. \"An application of combinatorial optimization to statistical physics and circuit layout design.\" [Operations Research 36.3 (1988): 493-513.](https://www.jstor.org/stable/170992?seq=1)\n",
"\n",
"[7] Poland, Jan, and Thomas Zeugmann. \"Clustering pairwise distances with missing data: Maximum cuts versus normalized cuts.\" [International Conference on Discovery Science. Springer, Berlin, Heidelberg, 2006.](https://link.springer.com/chapter/10.1007/11893318_21)\n",
"\n",
"[8] Candes, Emmanuel J., et al. \"Phase retrieval via matrix completion.\" [SIAM review 57.2 (2015): 225-251.](https://epubs.siam.org/doi/10.1137/110848074)\n",
"\n",
"[9] Waldspurger, Irene, Alexandre d’Aspremont, and Stéphane Mallat. \"Phase recovery, maxcut and complex semidefinite programming.\" [Mathematical Programming 149.1 (2015): 47-81.](https://link.springer.com/article/10.1007/s10107-013-0738-9)\n",
"\n",
"[10] Deza, Michel, and Monique Laurent. \"Applications of cut polyhedra—I.\" [Journal of Computational and Applied Mathematics 55.2 (1994): 191-216.](https://www.sciencedirect.com/science/article/pii/0377042794900205)\n",
"\n",
"[11] Deza, Michel, and Monique Laurent. \"Applications of cut polyhedra—II.\" [Journal of Computational and Applied Mathematics 55.2 (1994): 217-247.](https://www.sciencedirect.com/science/article/pii/0377042794900213)\n",
"\n",
"[12] Poljak, Svatopluk, and Zsolt Tuza. \"Maximum cuts and largest bipartite subgraphs.\" [DIMACS Series 20 (1995): 181-244.](https://arxiv.org/pdf/1810.12144.pdf)"
]
}
],
"metadata": {
"celltoolbar": "Raw Cell Format",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Large-scale QAOA via Divide-and-Conquer\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"[Quantum Approximation Optimization Algorithm](./QAOA_EN.ipynb) (QAOA) is a promising hybrid quantum-classical algorithm to solve combinatorial optimization problems approximately. However, its applicability is restricted by the qubit limitation for large-scale problems and its execution time scales exponentially with the problem size. Detailed and other limitations can be found in [1].\n",
"\n",
"Divide-and-Conquer (DC) is a largely used technique to address similar challenges as those listed above, such as quicksort and fast Fourier transform (FFT). It recursively breaks down a problem into several subproblems of the same type until these subproblems can be solved directly. \n",
"\n",
"DC-QAOA proposed by Junde Li et al. in 2021 [2] applied such technique on QAOA to solve the Max-Cut problem. The methodology presented below adopts this DC-QAOA scheme with some modifications."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Methodology"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Large Graph Partitioning (LGP)\n",
"\n",
"Let $G(V,E)$ be an undirected graph with $n$ vertices and $k$ be the qubit (vertex) limit, i.e. available qubit size in NISQ computers. LGP partitions $G$ into exactly two subgraphs $G_0$ and $G_1$, and at least one node is shared between these two subgraphs so that no edges of $G$ are missed. Those shared nodes that enables this separation are separation nodes. Note that number of separation nodes should be smaller than the max qubit limit. \n",
"\n",
"The following code shown is to define such partition."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T06:51:46.909218Z",
"start_time": "2021-05-11T06:51:45.642375Z"
}
},
"outputs": [],
"source": [
"import networkx as nx # version of networkx >= 2.5\n",
"import matplotlib.pyplot as plt\n",
"from itertools import combinations\n",
"\n",
"# Partition a graph into two subgraphs\n",
"def NaiveLGP(g, k):\n",
" E = list(g.edges)\n",
" E = [(min([u, v]),max([u, v])) for (u, v) in E]\n",
" E.sort(key = lambda tup:tup[0])\n",
" V = list(g.nodes)\n",
" V.sort()\n",
"\n",
" counter = 1\n",
" while counter < k:\n",
" num_nodes = counter\n",
" nodes_combo = list(combinations(V, num_nodes))\n",
" # Check suitable separation path\n",
" for p in nodes_combo:\n",
" V1 = [x for x in V if x not in p]\n",
" E1 = [e for e in g.edges if e not in g.edges(p)]\n",
" G1 = nx.Graph()\n",
" G1.add_nodes_from(V1)\n",
" G1.add_edges_from(E1)\n",
" S = [G1.subgraph(c).copy() for c in nx.connected_components(G1)]\n",
" if len(S) == 2:\n",
" # Add the seperate paths to two subgraphs\n",
" V_S0 = list(S[0].nodes)\n",
" E_S0 = list(S[0].edges) \n",
" V_S1 = list(S[1].nodes)\n",
" E_S1 = list(S[1].edges)\n",
" for (u,v) in g.edges(p):\n",
" if u in V_S0 or v in V_S0:\n",
" S[0].add_edges_from([(u,v)])\n",
" if u in V_S1 or v in V_S1:\n",
" S[1].add_edges_from([(u,v)])\n",
" if u in p and v in p:\n",
" S[0].add_edges_from([(u,v)])\n",
" S[1].add_edges_from([(u,v)])\n",
"\n",
" return S\n",
"\n",
" counter += 1\n",
" print(\"G has connectivity above k\")\n",
"\n",
" return {}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One example for illustration is given below. The graph is a random with $10$ vertices and the qubit (vertex) limit is $9$ vertices. Then red vertices are those selected to be removed so that the rest is disconnected and can be partitioned. We then add separation nodes with incident edges back to these two subgraphs to avoid missing information of the graph. "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T06:51:47.579620Z",
"start_time": "2021-05-11T06:51:46.912332Z"
}
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA1MAAADnCAYAAAD7CwxiAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Z1A+gAAAACXBIWXMAAAsTAAALEwEAmpwYAABJFklEQVR4nO3debzc8/XH8dc7+yKJfS+x7wSt2tdYf7ZaSqKEUiWWCkW1SpVWKU0qYpdYY09RlBIttRWlqCX2NYgt673Zz++Pz0SSe2du7p3M3O/M3Pfz8biPxJ3vfJ3LnZnP+SznKCIwMzMzMzOzlmmXdQBmZmZmZmbVyMmUmZmZmZlZEZxMmZmZmZmZFcHJlJmZmZmZWRGcTJmZmZmZmRXByZSZmZmZmVkRnEyZmZmZmZkVwcmUmZmZmZlZEZxMmZmZmZmZFcHJlJmZmZmZWRGcTJmZmZmZmRXByZSZmZmZmVkRnEyZmZmZmZkVwcmUmZmZmZlZEZxMmZmZmZmZFcHJlJmZmZmZWRGcTJmZmZmZmRXByZSZmZmZmVkRnEyZmZmZmZkVwcmUmZmZmZlZEZxMmZmZmZmZFcHJlJmZmZmZWRGcTJmZmZmZmRXByZSZmZmZmVkRnEyZmZmZmZkVwcmUmZmZmZlZEZxMmZmZmZmZFaFD1gHYXBLtgd2AHwErkP7/fAH8FbglgikZhrdwpLWBnwLrAz2AicALwJVEvJdlaGYtJi0KDAB2ARYHpgEfACOAx4iI7IIzM7NKUdNjOwNA/szPnkRX4KTcVzdgkQaXTCatIl4P/C6CT1ozvoUi7Qn8GtgQaA90nOfR6cBs4BngHCL+2erxmbWEtAZwFnAAMAvoPs+jAUwBvgEuBK4gYmarx2hmZpmr6bGdzcfJVMYklgRGA2sAXRdw+QxgErBzBC+UO7aFIgn4A3A86U1kQeqAs4i4uKxxmRVL2gG4l/Q6bb+Aq+uAZ4G9iJhc7tDMzKxy1OzYzvJyMpUhiUWA54DVmH/FpilBms3YLII3yhXbQpPOB05g/pn7BakDziDikvIEZVYkaQvgEZo3MTDHVOA/wA5EzChLXGZmVlFqemxneTmZypDESOAHQJcWPnU28AmwSgSzSh7YwpJ2Be6iZYnUHHXAdkQ8X9qgzIokdQc+BhYt4tl1wFAiflHSmMzMrCLV7NjOCnI1v4xILE2BF9uNN8LYsTBhAowZA0ce2ejp7UgDu13LHWeRziRfItWpE1xzDbz/PkycCC++CLvt1vCqLsCp5Q/RrNn6UahYz2KLwahRMHly+r3u16/hFd2AgUgt/VA1M7MqI7EUBcZ2//gH1NfDpEnp643G60+VPrazApxMZeco0rJuI+efD717Q69esPfecN55sMkmjS7rAZxW3hCLIK0GbJr3sQ4d4KOPYLvt0g935plw++2w8srzXtUO2BtpiVaI1qxp6ezfL2h8cDgZNgymT4dlloFDDoHLL4d118135YFljNLMzCpDwbEdwPHHQ48e6WvttfNeUpljO2uSk6nsHE+BQ4mvvZbGZwAR6Wu11fLe4/sSy5crwCL9hEKz+HV1cM458MEH6Ye6/3547z3YtFHuFcAhZY7TrDn6AMvmfaRbN9h/f/j1r2HKFHjySbj3Xjj00IZX9gAGlTdMMzOrACew4IITC1KJYztrgpOpDEgIWKapa4YNS+OzMWPg00/hgQfyXjYNWKkMIS6MdWnugcull4Y114RXX234SFdgzRLHZVaMVaHA3vU114SZM+Gtt+Z+76WXYL318l1daa9TMzMroeaM7c4/H774Ap54Im3SKaASx3bWBDftzUanBV1w3HFwwgmwxRaw/fYwbVq+q8b3gv2flh4teYDFehTYoTkXdugAN98M11+fMsbGepU0MLPidKfQpNMii6Szf/OaMCHt32jMZ6bMzACJLsBWwJKAgK+BpyOYlGlgC6/Jsd3pp8/deXTwwfDXv0KfPvDuu3kvL6aAl2XEK1PZmE4Te2rnmD077RxacUU49th8Vyw6AUZvFhGqlK8d4O4F/vRSqrIxfXraQJzfVwu8j1n5TaTQytTkydCz5/zf69kznSxurK7UgZmZVROJVSUGA18Ao4Crcl+3A59LXC2Rd2m/EknqKGlNSXtLOhXaDYNZBcfVzz6bPjamT4cbbkjjuz32KHj7iQUfsYrjlakMRBAS75N6ECxQhw4Fz0x1BvLPaWTnOVIlmsJ7hq+9Nh3Y32OPtE2qscnAy+UJz6xFXqPQbOObb6YX5+qrw9tvp+9ttFG+basAr5crQDOzSpbb/nYecDJpEr/QCs7hwCEStwA/jSDvAKG1SVoSWGuer7Vzf/YmlTIfk77ieZi6G3RfoTn3jUhzy3lU4tjOmuCVqexcBExp+M2lloKDDoLu3aFdO9hll1RtefToRs+fDfwtouJWcIaTlu3zu/xyWGcd2GsvmDq10FXtgNvKEJtZy0S8CeTNjqirS2XRf/vbVIxiyy1hn33Squu8l8Gsa2C0VOBj08ysRuUSqauBn5G2Oze1Fa4DaSL2YOBeifbljzDJrTKtLWkfSadJGi7pSUlfAm8DfwK2ByYANwAHAItGxGoRsUdEDIqIK6D7ueQZ2/XqlcZznTtD+/bQvz9suy08+GDDK2cHzHioAsd21gQ37c1I6pA9+wtoN99ZiiWXhDvvTBPc7dqlwneXXJLaMzUwBdglgqdaK+Zmk+4B9qJhUrXSSukHmjp1/hWpn/4URo4EYBbMElzdLiLvxkazVicdQJokaHwYarHFYPhw2Hln+Oor+MUv4JZb5rukHib3gPdmQXtgMHBzRNS3RuhmZlmSOA04i5afAaoDhkdwQulikUjntBquMK0FrExqzj4GeINvV5t4AxgXzRwsp7Ed42iwO2fJJVMhsbXXhlmzUo+pX/8aHnmk4R3qZ8Fu38Dj5wJXRUTBWWerHE6mMpB7QR8Kf74cjukInZpX/W6uGcD/gE0jFnz2qtVJ3wMeo4jyoPUw+/vw/CvQLyK8zG3ZkzoC7wAr0PLV/CnALwVDgR1JJdK/B1wJXBYRn5UyVDOzSiHRjZRY5E2kDjoIzj47zbN+9hkcfniqcjePqcAqEbTofVJSJ9IxinmTpTnJk5g/WZqTML0TEXlLfbWUxEXAsaSm7S2RG9t1/AnMPBvYBPgDcI2TqsrmZKqVSVqWdOByZVjix/DlBcCWND/xmEk6vNkngnFlCnPhST8mDSBb8mZSPw36dYE1SI1SzwSubO6MkFnZpGbUzwM9aX5CVQf8BTiUeX6HJa1F2vJyMHAvMDgiXiptwGZm2ZL4MfBn8jQ979s37bg56KBUmGG55dL3x46d77KpwPkR/LbxvSVgKeZPmOb8/TvAh8yfLM35+xflHlNIdAAeZCHHdpI2BX4DbAycD1zrpKoyOZlqJbkX/kGkN5argd9GxHSJzsCtQF/yvOE0UEc67Lh9BGMXcG32pMOAy0l7pJsqdjKdNCNzMBH3padqXeA6YDxwZER8VNZYzRYkJUH/JCVUTU0SBOm1eiNwPBF5qwFKWhw4mtTA+03SFsD7I2J2CaM2M8uExBgK9Ix88slUi2r48AXdJb6GZXeAcavTeGvebPInTO9ExPTS/BTFKeXYTtJ3SUnVRsxNqkqyimal4WSqFUhaipRUrAsMiIjn5n+cdsCewGmkZd32zD2kOZv0QhsHXAjcGFFFZZaldUgVfA4hlZie901lEmnJ/RrgEiLem/+p6kD6bzIIOB0Y4VUqy5S0KHAkcArpd3kR5p4NnEZKpB4DLiSiWQ3glLYRHkj6Pe9FmnC5LiIaHWI2M6sGuWSijjwr+e3aQX09nHUWHHUUdOkCd98Np56ary7VFGDj9+CtV2iwNS8ivizvT7FwSj22k7QZcDawIfB7YLiTqsrgZKrMJO0HDCPNUp+1oCVaidWB/YDlSC+6z0m9cJ+syPNRzSX1IA0Y1wAWI/WReg0YxQIO40vaELgeGAv8JCIqf1XOapvUjjTjuCWwNHNnFu8g4uPibimRGlmeDGwLXAtc6lVZM6s2EssA75Fnm9tyy6XtfM8/nwr7zpgB99wD//wnnHlmw6tjImj7CF4sf9TlU8qxnaTvk5Kq9ZmbVGW6EtfWOZkqk9wWnqGkw+aHR0TlVd2rIrkDpb8kHeo8GRjpVSqrVZJWBU4EDgMeIp2rejbbqMzMmkdiMeAz8pRCX3RR+OYbGDAgNa8F2G+/lEhtskmjW00Ctogo0KKiDZO0OSmpWpeUVI1wUpUN95kqA0l7Aq/w7WFCJ1ILKyKmR8RvgN2BM4C7JC2TbVRm5RER70bEScAqpEbYt+d6nhyQ2/5qZlbJJlCg5+T48fDRR6lp7RxNTI3OWcWxBiLimYjYnVTM6AfAm5KOzk0+WytyMlVCknpJGgFcAvSPiJMionrON1WBiHgB2JS0Z/olSQdmHJJZ2UTEhIj4E7A6qUDFIOAtSSdL6pVtdGZm+UUwm1TNNG9BnREj4IQTYKml0krVoEFw3315b/WfCCr6bFTWIuLpiNgN6A/sT0qqfpI7j2utwMlUiUjahbQaVQ9sGBGPZRxSzYqIaRFxBrAvcK6kWyUtmXFYZmUTETMj4s6I2IpUFfR7wLuSBktaJePwzMzyuZg0Jmrk3HPhuefgzTfh9dfhxRfhd79rdNkkUnEGa4aIeCoidiUV/PohKak60klV+fnM1EJSKqxwEbAbqYR3o37WVj6SugLnAf2AYyPinoxDMmsVkr5DKqt+JKmC4GDgSZ8lNLNKICFSoam1KLDlbwG+AJaPYGZJA2sjJG1NKqm+KmmcdGNEzMg0qBrllamFIGkH4GVSD6UNnUi1voioj4hTSLP1F0u6QdJiWcdlVm4R8VFEnA70JlWFGgE8K6m/ZyLNLGu5KnUHwKxiGs3WAfs5kSpeRDwREX2BAaTVqjckHeHPh9JzMlUESd0lDSWVOz8uIo6MiAlZx9WWRcS/SA3tJgCvSNo945DMWkVETI6IYaTZ33OBnwDvSfpFrqqomVlG1Al2nAoz6ilwfiqPOuCgCJ4oY2BtRkT8KyJ2Ao4ADgVel3S4ixmVjpOpFpK0FfBfYFFgg4h4INOA7FsRMSUiTiCVk75c0jWSemYdl1lriIjZEXFvROxAahS5DvCOpMskrZlxeGbWxkhaD3gAHv8JdNwYeByYCuQr3z2TdL7qOWC7CPKXo7CiRcTjEbEjaWv44aSVqgFOqhaez0w1U+5szrmkaikDI+LubCOypuSSqD8Cu5LOso3OOCSzVidpOWAg8FPgWdK5qkd9rsrMyik3gfMP4NSIGDn3+/QmnfU8GOhFOks1EfgrMCSC11s/2rZJ0vbAOcDypPHtyIho9rbKXC+xI4D/AxYDZgAfA8OBByOYVeKQK5aTqWbIdZu+jnQ+6riIcJnOKiFpV+Aa0hv1aRExOeOQzFpdbjLoR8BJpBngwcAtETEty7jMrPbkKow+BvwmIoZnHY8VJknA9qSkallSUnVLU0mVxBq5639A2rrZrcElk0grkIOBwREUc2auqrSZZEqiK9ARmJQ7FNmM56gzqbv0j4ETI+L2MoZoZSJpUWAIsA1wREQ83vzn0hHoTvq9aTOzLFabch+cu5D6VW0EXA5cERHjMg3MzGpCrsroY8DFubOcVgVynw07kJKkpZmbVM2a/zq2B+4lJVDtF3DbelI1x10i+LrUMVeSmj4zJbGpxE0SU0mZ8pfATInnJA7IDZQLPFebAM+Tzh1s5ESqekXE+Ig4nDSAvCXXm6fhTMq3JFaU+J3E18A0Uvf1GRIfSZwksWirBG5WYpE8lGvwuBOwIjAmd75w/YzDM7MqlttWPBoY5kSquuQ+Gx4FtiVtDT8GeFXSIZLaA0hsBtwP9GDBiRRAV2AD4J9So9WrmlKTK1MS6wO3AqsAncn/P30SMAs4OYIRc5+rjsCvSL9MJwM3+3xB7ZC0BDAU2BQ4PCKenvsYiwLXk2buAbrkucUU0u/TcOCkCNyzwaqapKVIZ6oGAv8jbc14KCKaW3nLzNq43PvIP0mrGedlHI4tpNxKVV/SStVisNT58PkQKKr1TD1wcwQ/KWWMlaTmkimJbYAHSFuzmtMkro60p/NMSRuQBtOfAj+JiLHli9SyJGl/4FLgBuBsiEWBp0gHMTs34xZ1wAuk5eu8Hd7NqkluW/PBpBXczqStsTdGRF2WcZlZZcv1dnwUeCAifpV1PFY6uaRqZzhuGPxhVVik4I621VeHV16BO++EQw9t9HA9sGwEE8sYbmZqKpmSWA94BlikZc+MOhjxKBy5OXA6MMKrUbVP0tLAZdBzPfi0C3RbkdSAubnqSdWK9opodv8Ms4o2z4HkQcDmwNWkbTueXDKz+eQq5z4MPAmc4rFTbZLiFWh6K/hDD0HXrvDBB3mTqSnALyK4tFwxZqnWzkwNJ61I5bX66lBfDzfe2PARdYMf7QGDdomI4X4zaBtyh+4PhFGvQLuVaZBIHXccPPccTJ0KI0bkvUVXYDtgn7IHa9ZKcnvn/xERewNbkcoX/0/SjbmzpGZmSOpOOkPzH5xI1SyJtUGrNnXNQQfB+PEwunATmu7AiSUOrWLUTDIlsQ7poFvBrX3DhqXBcX4dp8Gfdi9HbFbJoj3stCN0afR7M3YsnHceDG+6sGt34LRyRWeWpYh4KyKOB1YDXgHukfSYpH3nHEo2s7Yn127hXuAt4HgnUjWtNxQ+H96jB/z2t3DyyQu8z/IljKmi1EwyRcp4C1bnW3DWrK7AIKlZFUqsdvwf0CnfA3/5C9xzD3z11QLvsZHEmqUOzKxSRMQ3EXEhsCqpnPoZpCqAJ0rqkW10Ztaacucr7yJVuv2Ji9XUvCZrEJx7Llx7LXzyyQLv05zz6FWplpKpH1LgvEsLsubOwMYljssq249IZT4XRgdg34UPxayyRcSMiLiVdJbqMFLvtvck/VHSStlGZ2bllqt4fAupKeuAhn2IrCZNhPz9WTfaCPr2hcGDm3Wfmi3W1ZLD9pWuZ6EHWpA1zwaWLGVQVvFKsezckdQ53KxNyG3peQp4SlJv4ATgRUmPAIMj4pks4zOz0stt7b2BNPH8g4hwa5C24TUKrCptvz307g0ffpj+eZFFoH17WHdd2HTTRpe/Ub4Qs1VLK1N5lyBbmDVD8xqRWe0o1WugliYmzJotIt6PiFNIff2eBkZKelrSDyX5dWFWAyS1A64BlgL2j4jpGYdkrSSCT4AnyLM6ddVVsNpq0KdP+rriCrj/fth110a3mQT8sdyxZqWWPujqyLNdq4VZs4CvyxqlVZovS3CPWaS942ZtVkRMBIZIGkqqcDkI+GPun6+JiPFZxmdmxcm1S7iUVIhm94iYmnFI1vr+SNrePV/rofr69DXH5MmpAvKXjUdWs4C7yxphhmppZephaNzrpwVZM6T/Hi+WNUqrNKOAyfkeaN8eOndOf8779zymkn7/zNq8iJgVEaMiYhtgf9I51HclXSJptYzDM7MWyCVSFwObAHtGxJSMQ7JsPAJ8BMxs6qJzzinYY+r3EYUrAla7WkqmLiKtTs2nvh4+/3zuVxNZ83Tgmgg849K23EaBLaJnnpl+V844I705TJ2avpfHJ0DBovtmbVVEPB8RhwAbkj5Qn5F0t6TtcoM0M6ts5wE7kFakJmYdjGUjgtlAX9LurSYTqgbqgPtIY/SapVppDSAhUr+DYmc+pwLrR/BO6aKyaiAxFPgpTZTWb8IU4MQImu5GZWZzmnweBpxEeu38Cbjd5y/MKo+kM4F+wHYRUYot8VblJFYC/gksTSqZXsDsgHZ1wE3AcRHUdNXHmkmmACR2Av4KdG3hU6cAN0QwsPRRWaWTWA54GViCJnop5DEDGAN8zyuaZs2XO8y+O+lc1TrAMODKiFhwVzczKztJp5AmGbeNiM+yjscqh0R34BDgdFJS1YVUgyGAqTCrAzw1CbbZH3gsIn9Z9VpSU8kUgMRhwBU0P6GqA0YDP6j1zNkKk9gA+BepiElztr9OBz4jJVLjyhmbWS2TtCFppeoHpG23QyKiZkvomlU6SccBp5BWpD7KOh6rTLkdYVuQ+g0uSdrh9Tm8eS+s9RRpa+grWcbYWmoumQKQ2BMYCSHQIgUum0pahbgKGOREyiRWBx5i7vJ1nlWqWbOh/VRSoZK9I1z90awUJC0DDASOAf4DDAYeiVr8kDKrUJKOBM4mJVLvZR2PVSdJZwHLR8QxWcfSGmoymQKQ6AIjL4DNj4JV2wHTcg+1Jx2euxS4PIKxmQVpFSc307IDcGruz2mkpWvB7M5w5yzYa5uIri9kGadZrZLUhbSFZBDptTcEuNnlmM3KS9IhwIXADhHxZtbxWPWStByp2W/viJiQdTzlVrPJFICkO4C/Q8xZbegIfAO8U8slGq00JJYAViT1VZgAfAB6Ejg+Ih7PNDizGper9teXlFRtStq+fVlEuKebWYlJ2p80ydw3Il7NOh6rfpJuBZ6KiEuyjqXcajaZktSTVBN/lYjwViwrCUlnACtFxLFZx2LWVkhaB/gZcBCp8ePgiHg506DMaoSkPYFrgV0j4r8Zh2M1QtI2wDXAOhHRqA9sLamlPlMN7Qs85kTKSuxW4ABJxZRRN7MiRMTrub33q5NaYPxN0mhJe+YqA5pZAxId0pGHpq7RzsBwYC8nUlZiT5COSuyUdSDlVssfQv2AkVkHYbUldyD3TWDnrGMxa2si4quI+D2wCjACOAd4XdLAXA8rszZNYl2JqyQmkarOTpaYIfG0xA8kOsy9VtuRxkn7RcSzWcVstSlXPGgYcFzWsZRbTW7zk7Q0acC7QkRMyToeqy2Sjgc2j4gfZR2LWVuWO1e1Delc1TbA1cClEfFJpoGZtbJcNdqRwPqk8+Ed8lw2iVSA6xTQG8A9QL+IGN1qgVqbImkR4ANg44j4MOt4yqVWV6YOBO53ImVlcgewp6RuWQdi1pZF8nhE/ADYnNTS4BVJN0v6bsbhmbUKie8Cz5MKtXQlfyIFqY/iYjDrMrjoEWCAEykrp4iYDNxIanlRs2o1meoH3JJ1EFabctXE/g3slXUsZpZExNsRcSKwKqkP3F2S/iVpP0ntMw7PrCwkVgMeAXrR7DFd+y7ws/YQa5cxNLM5LgOOlNQ560DKpeaSKUkrA2sDf886FqtpI0lJu5lVkIgYHxEXAasBQ0k9496SdFKuyqtZLbmKtOL0rUmT5v+aORMuaVScukNn4PcSy7VWoNY25XqWvUTaNVaTai6ZAg4G7oqI6VkHYjXtL8AOkhbLOhAzaywiZkbE7RGxBdAf2AJ4T9KfJPXONjqzhSfRG9iSBmO5Hj3mfi27LNTXwx13FLzNT8sbpRlQ44UoajGZ6o+r+FmZRcRE4GFg/6xjMbOmRcQzEXEQsDEwC/iPpDslbZUrYmFWjY4Hmvz93X9/GDcO/vWvvA93AU6ct8KfWZncBywvadOsAymHmkqmJK0HLAHkf9swKy1v9TOrIhHxYUScCvQGHgOuB/4t6WD3jrMq1B9o8hzKgAFwww1N3qM9qXiLWdlExCzgCmp0daqmSqNLOg/oEhE/zzoWq32SugCfAutFxNis4zGzlskVptiTVFp9VeBS4OqI+CbTwMyaQaKOVL0vr5VWgnffhdVXh/ffL3ibCcDhEdxd8gDN5iFpKVLT9dUi4qus4ymlmlmZym3VcKNeazURMRW4G/hhxqGYWREiYlZE3BMR2wP7AhsA70q6VNIamQZntmBNjuEOPRSeeKLJRArSNkFv87Oyi4gvgL8CR2QdS6nVTDIFbEZqRvdi1oFYm3ILaauFmVWxiHghIg4F1iPN1j8l6V5JO/hclVWoSU09eNhhcP31C7xHAF6JtdZyKXCspFrKP2oqmeoPjIxa2rdo1eBRYCVJq2cdiJktvIgYGxG/AlYG7if1SHlB0oBa7pNiVekRUkGVRrbYAlZYockqfnN0Ap4tcVxmhTxLSt53yzqQUqqJZCq37/2HuFGvtbKImAncgQtRmNWUiKiLiCtJK1W/BA4B3pf069zef7OsXQxMy/fAgAEwahRMntzk82cCIyOaXuEyK5XcgkfNlUmviQIUkvoCf4iI72Ydi7U9krYAhgPremXUrHZJWh84idQS4U5gSES8mmlQ1qZJvA6sXeTT64DvR/C/EoZk1iRJXYEPge9HxLtZx1MKNbEyRdri51Upy8ozpH4dG2UdiJmVT0T8LyKOAtYCPgIekfSQpN18rsoyMhCoL+J5dcDdTqSstUVEPXAdcGzGoZRM1a9M5cpTjwU2jIiPs47H2iZJvwc6RMRpWcdiZq0jd4aqH6m0ekdgCHBjbrBg1iokDgWupIky6Q3UAf8Gdo1gRtkCMytA0qqk38GVauH9shZWpnYHXnIiZRkbCRxcaxVqzKywiJgWEdcBfYATgL2BDySdK2m5LGOztiOCG4EDgcm5r0KmA1OB23EiZRnKbe97Fjg461hKoRYGfv3wFj/LWET8j1ROeausYzGz1hXJ6IjYE9gGWAJ4TdL1kvpkG521BRHcDyxNSurfIK0+TYDxABNJZdQvBdaN4AgnUlYBhgHH18IW6are5iepJ2nf+qq11k3Zqo+kM4DvRMTArGMxs2xJWhw4GjgeeAsYDNwXEbMzDczaBInVgGVg+yfhn32AMRFMzTgss2/ldvK8BRwSEc9kHc/CqPZk6lDghxGxV9axmElahbRsvXxEeNbPzJDUkbQFaxCwKPBn4LqIaLpotVkJSIqIqPqZf6tNkn4ObJRrmF61qn2bX3/SWRWzzEXEe6RZlr5Zx2JmlSEiZkTESGAz4AhgB1K/qgslfSfb6MzMMjUc2FPS0lkHsjCqNpnKNU3cErg361jM5nELKck3M/tW7lzVExGxPymx6gi8JOlWSd/PODwzs1YXEV8Do4Ajs45lYVTtNj9JA4GtI8IDV6sYkpYhHf5dISLqso7HzCqXpF7Aj4ETgU+BPwF3R8TMTAOzmuFtflbpJG0C/IVU/2BW1vEUo2pXpvAWP6tAEfE56dzUnlnHYmaVLSImRMRgYA3gYtK5qrclnZxLtMzMalpEvEDqF1u146aqTKYkrQysDfw961jM8vBWPzNrtoiYGRF3RcRWwA+B7wHvSRqSa25pZlbLhgHHZR1EsaoymSI1+borIqZnHYhZHn8BdpC0WNaBmFl1iYhnI6IfsBEwDXhW0ihJ29RCPxYzszzuADaStFbWgRSjKpIpic4Si0m0z33LjXqtYkXEBOARYD8kIXVDWpTUU8HMbIEi4qOIOB3oDYwmVb16TtIhkjqV4t8h0SH32dq5FPczMytGREwDrgUGAkhIYhGJHhIVP4lUsYM7iVUkLpaYQOrk/RkwQ5r+CZyyMvzvv9lGaFbYMfDkvXAu6Xd3IvA5MAPpZaRDkDx4MbMFiojJETEMWAs4h1T16l1JZ+QaA7eIRC+JEyU+AKaTPlvrJCZIXCSxckl/ADOzZulyBfQ9XJrxd2AG8A3wFTBDYrTEblJl5i0VV81PYingZmAbUrKXZwZu2gzoPBO4Ajg1gqqs/mE1KC1R3xqw5kzo1jH/VZNyf/6KiKGtFZqZ1QZJfYCTgH2AW4EhETGm6efQAbgIOBqYDXTPc9k0IIDHgEMi+Kp0UVsWXM3PqoHEDsD1UL88dGkHebc0TwKmAEdFcH/rRti0ikqmcjNiTwFLkjeJaqQOeBLYMwKfn7JsSZuRtvd1p3mrvnXACOAEKumFaGZVQdKypG0xxwDPAYOB0dHg/SS3je8BYHOgWzNuPR34Atgigo9KGrS1KidTVukkDiKNhbo28yn1wM8iuLp8UbVMxSRTEosBLwIrwrdno5qjDrgPODiCyvhhrO2RVgf+A/Rs4TOnAH8g4rzSB2VmbYGkrsCPSKtVs4AhwMiImJo7b3AnsDvNH6wAzAQ+AjaJYHwp47XW42TKKpnEjqQxfEvemyAlVP0iuKf0UbVcJe09/DWwLA0SqX/8A+rrYdKk9PXGG42e1w3YA+jbKlGa5XclsEij7y62GIwaBZMnw/vvQ79+Da/oDvyKVO7fzKzFIqI+Iq4G1gdOJZVXf1/S2fDyD4FdaTBYOe44eO45mDoVRozIe9sOwPLAL8savJm1SbnzTzeTJ5G68UYYOxYmTIAxY+DIIxs9vStwvdSsXWxlVxHJlEQX4CjIX1Ho+OOhR4/0tfbaeW/RHfh5+SI0a4LUG9iSfK+nYcNg+nRYZhk45BC4/HJYd91GdyBXwcbMrFiRPBQRuwE7AivANzeR53zU2LFw3nkwfHiTt+wM/NTV/sysDHYl/9lNzj8feveGXr1g773Te9UmmzS6rB2wX3lDbJ6KSKaAAxfy+QK2lVixFMGYtdBAyFO6s1s32H9/+PWvYcoUePJJuPdeOPTQhld2Bo6hROWOzcwi4jWI38G2eQs0/eUvcM898NWCS0yIChmwmFlNOQ3oke+B115L89AAEelrtdUaXdYDOL2M8TVbpSRTh1LgPyikDPWLL+CJJ2C77QreYzawdxliM1uQfuRbVV1zTZg5E956a+73XnoJ1luv0H22KkdwZtZm7Q1a2LPEPUif0WZmJZFb7d6mqWuGDUvz0GPGwKefwgMP5L1sHYklyxFjS1RKMrVMoQdOPx1WXRVWWAGuugr++tf0z3l0gez/g1qbtGje7y6yCEycOP/3JkxI+1Xz8++vmZXSUqTPxoVV8DPazKwIi0HTVbiPOy4Nl7beOh09nzYt72XTqYCxU6UkUwWr9z37bDq7P3063HBD2im1xx55LxWV8/NY25L/927yZOjZoLhfz56pkkpL7mNmVpyWVMZtjfuYmUEz31Nmz07j/hVXhGOPLXhZ5mOnzAPIaXZjwIgCrbxSs8FvShWQWQtMzPvdN9+EDh1g9dXnfm+jjeDVV/NdHfj318xK6ysWMPvbgvuYmZXK1zSvnyyQhlJ5zkwBdKQCxk6VkkyNIvWLmk+vXrDLLtC5M7RvD/37w7bbwoMP5r1HAA+XOU6zfP5G6skyv7q6tDb929+mYhRbbgn77JNqfjbWCXi6zHGaWdvyMETj9ybSZ+qcz9Z5/57HFOCucgZpZm1LBPVA3pnlpZaCgw6C7t2hXbuUB/TrB6NH573VZ7mvTFVKMnU9eWLp2DGVQ/ziC/jySzjhBNh33/nP88/j1QheK3OcZvkModDs78CB0LUrjBsHt9yS1qlfa/RrOhO4hYiC+//MzFpCUi/QzvBax3yPn3lm6jF1xhmpwOjUqel7ebQDbipnrGbWJl0ANBr3RKSh0scfwzffwEUXwUknpZoJDUwBLoxgYYvsLDRFZB4DABI3AP0pbm/2ZODHEdxR2qjMmkl6EehT5LPrgM2JeKV0AZlZWyRpVeBE4DDgIXjgVdj9dPI1FV+wmcANETRumWlVQVJERP7DEWYZylX0Gwf0XNC1BdQDy0Q0TshaW6WsTAH8mjwZajNMA14D7i5pNGYtM5A8W1WboQ64y4mUmRVLyTaSRgHPklbK+0REP9j9AmAMxZ2dmgScU8JQzcwAiGAaaeKn2LHTLyshkYIKSqYi+ADYhfTm3dzlsqnAB8BuEcwoV2xmCxTxNKkXS0veFOqAp8CzvmbWcpI6SjqElEANBx4FekfEaRHxIUDus3EX4EPS5GNzzCYV1ukbwYelj9zMDCK4nrTdr6Vjp6siGFKWoIpQMdv85pBYh3Sgf3HStoQ8y9OzZkP7acATwP6VkpmaIe0I3BXQXoUbUU8jTRjcBBxL5D8gbmaWj6TFgaOB44G3gMHAfRExu/Bz6EUqJLEFqeBNhzyXBekcwpekScoxJQ7dWpm3+Vk1kDgKuASmdoQu+d6bICVR7YAzI7i49aJbsIpLpgAk2gF9gVNJHZLnDD7bwaxOcGs9/HDriI55K4GYZUrqdCuctREMWie98Kfz7e8vs4HLgcuI+CjLMM2sukhaC/gZ0A+4FxgSES+27B6sD5xEOqM8k/SeJKAz8DhwIfBoBAUTM6seTqasWkjHrQwdXoc/fQXtF4dvd5x1BMYDFwHXRWRfCr2hikym5iWxFLA80A2YAF98AEu/Auzf0g8Rs9YiaTjwSsDtwDKkmeDxwLtElKLvi5m1AZIE7AgMAjYDrgQui4hPF+6+dAd6A71Iq1GfRPDlwkVrlcbJlFULSacCG0AMAFYBliBN9HwNvFvJEzwVn0zlI+l3QKeIODXrWMwaktQFGAusHxFjs47HzKqPpM6k1aOTSDOzg4GbIqI+y7isujiZsmogqT1py3K/iPh31vG0VMUUoGihW4CDJVVr/Fbbdgf+60TKzFpK0tKSziYVVzoIOB1YLyKudiJlZjVqN+ArUjGdqlOVyUhE/A/4Btg661jM8ugPjMw6CDOrHpLWl3QtqYz5CsBOEbFbRDwY1biFxMys+Y4DhlXre11VJlM5I0mDVrOKIaknqQzxXVnHYmaVTVI7SbtL+jvwMPA+sGZEHB0RLrBkZjVP0mrA94Dbso6lWFV5ZgpAUm/gOWCF8IF+qxCSDiMVR9kn61jMrDJJ6kbqS3cSqVrtYODWiGhuHyizZvGZKat0ki4CZkfEaVnHUqxCtdwrXkS8L+lNYGfg/qzjMcvpD1yXdRBmVnkkLU/aznI08DQwEPhntW5tMTNbGLmJpcNJK1NVq5q3+UEqRNEv6yDMIB0cBzYH/pp1LGZWOSRtIulG4FVSKfItI2LviPiHEykza8MOBp6JiPeyDmRhVHsydQewZy6zNcvagcD9ETEl60DMLFuS2kvaV9JjwD3AK8CqEXF8RLyVcXhW4yTaSywOSyPROet4zBrK9dA7HhiWdSwLq6qTqYj4HPg3sFfWsZiRVkldxc+sDZPUQ9KJpKp8ZwCXk5KoCyPim2yjs1omIYnNJe4A6oFP4T2AOonXJQ6X6JptlGbf2hzoCTyUdSALq2oLUMwhaQCwnw/8W5bmKYiyfETMyDgcM2tlklYGTgCOAB4lFZV42tv4rDVIbADcSSqr35X8k+WTc3+eDQyOwL+blhlJNwEvRsTFWceysGohmeoJfASsEhFfZx2PtU2SfgH0johjso7FzFqPpC2AQUBfUvGZodW+/9+qi8S2pEJc3YHmVO6rA24ABjqhsizkzpiPAVarhbF7VW/zA4iIiaT+HPtlHYu1ad7iZ9ZGSOog6YeSngZuBp4iTaac7ETKWpPEuqREahGal0gBzCnNf1a54jJbgKOAu2ohkYIaSKZy3MDXMiNpPWBx4ImsYzGz8pG0qKSfA++QtvT9EVgjIobkJvbMWtvVpBWp+ay8Mtx/P3z9NXz6KQwdCu3bz3dJd+AXEiu1UpxmQJqMAo6hBgpPzFErydQDwMa5Hh5mra0fqeHm7KwDMbPSk7SapEuAd4GNSY25t4mIURExK+PwrI2SWAPYhDwrUpddBuPGwXLLQZ8+sN12MHBg41uQep2ZtaY9gY8j4sWsAymVmkimImIqcDdwUMahWBuTK+3Zj9TzzMxqhJLtJN0NPANMATaMiEMi4vlsozMD4ESgfb4HVlkFbr8dpk2Dzz+HBx+E9dZrdFln4FiJTmWO02xex1FDq1JQI8lUjhv4WhY2A2YANTPDYtaWSeok6VDgP8BVpLK9vSPijIj4ONvozOZzINAx3wNDhsDBB0PXrrD88rD77imhKmDzMsVnNh9Ja8G3lSdrRi0lU48CK0taI+tArE3pD9zi8sdm1U3SEpJ+SWrMMwD4NbBORFzuRtxWoXoWeuDxx9NK1MSJ8Mkn8PzzcPfdBe+zRDmCM8tjIHBtREzLOpBSqplkKiJmArfh1SlrJblDlAfhLX5mVUvS2pKuAN4GVgd2j4i+EXG/z0FahctbvU9Kq1CjRkH37rDEErDYYnDBBQXvUzNjQatckhYhVZG8MutYSq3WXkC3AP1z51jMym174KOIeDPrQMys+XLnoXaW9ADwGPA5sHZE/DgiXs44PLPmmpTvm4svnqr5XXopTJ+eKvqNGAF77JH3HgHURHlqq3g/Ah6LiA+zDqTUai2ZeoZ0oLJPxnFY29Afr0qZVQ1JXSQdCbwMDAbuAlaOiLMj4vNsozNrsQeAmQ2/+dVX8O67cOyxqRx6r14wYAC8nH+aoAPw7zLHaW1cbpGj5gpPzFFTyVTu3IoLUVjZSeoC7EvaWmpmFUzSMpLOAT4A9gdOBjaIiGtz1WDNqtGfgOn5HthvP9htN/jiC3j7bZgxAwYNanTZDOC6COrKHKfZNqRiKaOzDqQcVGvn5iWtD/yNNNvo/e5WFpJ+AJwYETtkHYuZ5SdpQ2AQcyc+/hwRr2calFkJSfwX2KjIp9cDfSLwVnUrK0m3AU9ExNCsYymHmlqZAoiI/wHjga0yDsVqWz9gZNZBmNn8JLWTtKek0aSJtbeA1SPiGCdSVoOOgWJWlmbVA9c7kbJyk7QcsDNwQ9axlEvNJVM5I0nnWcxKTlJPYFfSeQszqwCSuksaCLwOnAOMAFaJiN9HxFfZRmdWHhE8AxxCWmVqppnT4KF2sGjNVVWzinQ0cFtETMg6kHKpuW1+AJJWAZ4Flo+IGVnHY7VF0mHAARGxd9axmLV1klYEjgeOAv5FKizxL/d+s7ZEYjvSBF8noEeBy+acD7wCOj0NM4YAO3nF1spFUkfgfWDX3M6xmtQh6wDKISLek/QWaVnxgazjsZrTjxperjarBpK+SzoPtTtwE7B5RLydbVRm2YjgMYllgb2A00lVjaeTSp93IG0F/DNwdQSfw3QkdQYelrS9XztWJvsCb9dyIgU1ujIFIOl40ofrj7KOxWqHpKVIZzBWiIgpWcdj1pZIag/sQ0qiVgKGAtdExPgs4zKrNBJLAkuT2sV8A3wUwazG1+knwK+A7SLig9aN0mqdpH8Cl0XE7VnHUk61nEwtA4whbfVz2U8ridyZjK0i4pCsYzFrK3LnFH8MnEhqsDsYGBURjXrsmFnLSDoB+Bkpofok63isNkjaAHiIVF27po/c1GoBCnINGP8N7CUhiUUkFpNq92e20pPoLLGERMfct9yo16yVSOot6U/Ae8AWQP+I2CIibnciZVYauXLVVwGjcxPRZqUwELiq1hMpqOFkKjn2aXj4YtKhy6+Bz4AZEi9IHCTRKdv4rBJJrCTxB4lvSPvMPwGmSTM/g1/0gcefyzZCs9qlZCtJdwL/AWYBG0fEQRHxTMbhmdWkiLgQuJV0hmqJrOOx6iapF3AwKUmveTW5zU9iQ+A2iJVgdjdon++yScBs4OcRXNOqAVpFkliMdJB9R0CkveYNTJsJnWcC1wMnRuTvPm9mLZOr+rQ/cDKwOOmw/HURMSnTwMzaCEkC/gD0JVX5G59tRFatcltHt46Ig7KOpTXUXDKVKw96P9CNNCBekDrgkgjOKGtgVtEklgOeBpaDZq1Y1gH/BfpGtKS/h5nNS9JiwE9I5c3fJZ2Hui8iGh2WN7PyyiVUQ4DNgF08mWFNkpYFvg8sCswAPn8b/rUGvAT8NCIezzK81lJTyZTE+qQB8SItfGod8KsIhpQ8KKt4EouQthOtSsvaBdQDjwH/F8HscsRmVqskrUE69N4fuA8YEhEvZBuVmeUSqiuBtYDdXcTL5pN+P7YBfk5qQTSddGwogJgB7S+HuqNhky4RH2cYaauptTNTw4Hu+R446CB47TWYPBnefhu23nq+h7sB50v44GXbdAqpzPJ8idTaa8Po0TB+PLz1Fuy7b6PndQW2JvVRMLMFyJ2H2kHSvcCTwHhg/Yg4zImUWWXINbw+BvgAuFtSl4xDskoh9QAeJe0A2xPoAvQkLWL0AHp2hO4DYdEu8BZpu1/Nq5lkSmIdYH3ybO3r2xcuuACOOAJ69IBtt4V33210iyBtNbE2RKIDqdzyfB8W7dvDPffAfffB4ovD0UfDTTfBGms0usUiwGmtE61ZdZLUWdIA4AXgMtJKVO+IODMixmYbnZk1FBGzSe0IxgN3SHLBrrZOWoS0+2tz0tin4FGaDtCRNK46H+ms1gkwOzWzzU/iStILv9E2rSefhGuvheHDF3ibL4Fl8zW2s9oksS9wA2lG5VvrrQfPPJOS7zkeegj+/W84q/HbQj2wcQRjyhqsWZXJNbk+hlQi9xXSeaiHcgM1M6twucIwd5LOwxzslgRtmPR30va+lq5U1gFHEnFr6YOqDDWzMgUcQJ5Eql07+O53Yaml0latjz6CoUOhS/5fhc7AxmWO0yrLITRIpAqRYP318z7UAdinhDGZVTVJ60m6GngTWBnYOSJ2iYi/OZEyqx65HkE/JK1EXCcpb3lkq3HS94AtaZhIdeoE11wD778PEyfCiy/Cbrs1fHY34GKkWso55lNLP1jPfN9cZpn0//qAA2CbbaBPH9h4YzjzzLz3mA0sWcYYrfIsn++bY8bAuHFw6qnQoQPsvDNstx1065b3Hh2BZcsZpFmly52H2k3SQ8AjwEfAWhFxVET8L+PwzKxIETEN2A9YAbhSNTwotoJOIZ0Tn1+HDmmVYrvtoFevNLi+/XZYeeWGV/YktZ2pSbX0gsi7d7M+V7R66FD47DP46iv4059gjz0K3sezLm1L3tfAzJmp4MT//V/6vTnllPT+8HHhujQtqQJoVjMkdZV0NPAqcAFwC+k81G8jYly20ZlZKeQq+u0FrANckqv4Z22BtDhp903j8VJdHZxzDnzwAUTA/ffDe+/Bpps2vLI7cGr5g81GLSVTU/J9c/z4lDTPezSsiWNiAr4ucVxW2b4o9MArr8D228OSS6ZV61VXhWefzXvpLODzMsVnVpEkLSfpXFLFr71IfaL6RMR1uZlsM6shETEZ2IPUV+hCJ1RtRh+gee/pSy8Na64Jr77a8BGRfm9qUi0lU3+H/L1+RoyAE05I56YWXRQGDUpV2vJoB7xYvhCtAo0CJud7YIMNoHNn6No1rUwttxxcd13ee0wl/f6Z1TxJfSRdD7wGLE7qcr9XRDwatVLRyMzyiogJwK7ALsA5GYdjrWNRmqjc960OHeDmm+H669NZicbyH5SoAbWUTF1MqqrWyLnnwnPPwZtvwuuvp/Nxv/tdo8umA1dHMLXMcVplua3QA4ceCp9+ms5O7bRTOjc1fXreSz+O4LmyRWiWMUntJO0t6R+ksuavA6tFxHER8WbG4ZlZK4qIr0nNWg+QdEbW8VjZTSO1DypMghtvTIOk448vdFXNVoKspdLoIlWOWr24O8yYBf/ZKGLzRmuTVtukd26D7xwInYrZsjAFOCGCEaWOyyxrSn1FDgd+Ruo3Mxi4I1fhy8zaMEnLA48BwyJiSMbhWLlIm5D+Py9S8Jrhw6F371SQYGrBNYlPiFix9AFmr2ZWpiII4GgKrE4t4Nl1cP9bsMU9krYudWxWmXKNRM+DbXeE2ZObPE2X33TgXdKBe7OaIek7ki4E3gd2AI4ANouIkU6kzAwg13B7J+Bnkn6adTxWNi+SJtPyu/xyWGcd2GuvphKpqcDVpQ+tMtRMMgUQwT9oeUI1BfR32Hd9UunH2yVdLKlxCUirGZL6AM8BG8DYDaDLlqAJFDh3l8c04FNgJ28NtVohaTNJtwIvkUr+fy8i9o+IJ3weyswaiogPgb7AmZIGZB2PlUF67/8j+Qq9rbQSHHNM6jv02WcwaVL66t8/352uLG+g2amZbX7zktiDtFogCjdknZp7/DLg5xFpEC1pSeBSUvWSARHx77IHbK0m1839DFLlsZ8DN84ZJEqsCjwILEcq45lv299M0orU88C+EXzTGnGblYukDsC+wCBS37VLgGsjYmKWcZlZ9ZC0NvAoMCgiCp5Ftiol9QLGUlwRiRnAg0TsXdqgKkdNJlMAEp2BA4DTgDVJA+Ag9ZGaThowXBnBZ/mfrwOBocAI4Dcu9Vv9JK0PXAd8CRwVEY26RuXO3m1L6ofQl7kHL9uRekndBgyO4OVWCtusLJQ+HI8ETgQ+Jp2HuiciavaQsJmVj6QNgIeBYyLi7ozDsVKT9gNuIl/z3sJmk1rQbEREzbaQqdlkal4SKwBLA52Ab4B3IxZcVUTSMsDlpGRsQET8p6yBWlnkZt5/TtrGeQZp1n2Bv/gSi5M6vncHJgIfRuQvo25WLSStSkqgDiOtxA6JiPwd1MzMWkCpWMHfgMMj4m9Zx2MlJh0BDKN5CdUM0uT1tkS8Xda4MtYmkqmFkWtK1580a3s58LuIyF8g2yqOpLWA60l7fX8cER9kHJJZq8u9j21N2sq3LXANcGm+1Vkzs4UhaXPgXuDgiHg063isxKQdgSHAakBn0o6vedWRdvPcA5xIxLhWjS8DTqaaKVcC9GrSmYIBEeFtXhVMUntSOedfAmcDl0dEc4tLmNUESZ2AA0lJVE/SB+D1EdH4ILGZWYlI2g64E/hBRDwx9/t0BX4I/Ii0Y6gd8BVwO3BjBJMyCNeKkQp5nQzsSKpPMJO0EnUNMJyIr7ILrnU5mWqB3Ozu4cCFpEHJBT5fUHkkrUY6GxXAERHxTrYRmbUuSYsDPwWOI/XfGwzc7wkFM2stknYhnbHZE+Jt4CzSOU1o3LNoCimxGgn8JgKvmlvVcDJVBEkrkTLvRUmrVK9nG5EBSGoHHAucA/wO+LMHj9aW5La1ngQcTNpiMSQi/ptlTGbWdknaC1YfAa/OhE6Lkc6uN2Um6YzyThH8t+wBmpWAk6ki5VapjgbOAy4ABkfErGyjarsk9QauJRWLGBARY7KNyKx15N6LdiJt5fsuqZfHZRGRt1KpmVlrkVgW6t+ATr0aH60pKEgJ1fcieKt80ZmVhpOphSRpFVL59I6k6jV+4bei3EDyKOD3wEXAxd56aW2BpC5AP1IS1Z60le/miGhJ03Izs7KReAzYgjRGaonZwLvAmhF4oGoVrV3WAVS7iHiPdPjuNuBpSSfmtptZmUlakVSC9Rhgh4jwGTareZKWlnQ28D7pIPfPgfUj4honUmZWKSTWAr5HnkRq7bVh9GgYPx7eegv23bfR09sBywLblDlMs4XmQX8JRMTsiLiENPtyEPBobsXKykDJAOAF4Elg84j4X8ZhmZWVpPUlXQuMIVUV3TEido+Ivzenb5qZWSs7kdTsfj7t28M998B998Hii8PRR8NNN8EaazR6fnfSZJFZRfM2vxLLleQeBJwO/Bq40gOd0pG0LHAVsDLpbNR/s43IrHxyq9y7kd5T1gMuA66IiC8zDczMrAkSAiYD3Ro+tt568Mwz0KPH3O899BD8+99w1lmNbjUNWCaCCeWL1mzheGWqxCJiVkRcRGqM+WPgIUnfyTisqpdbjeoHvAS8DHzPiZTVKkndJB0DvEqqTHkjsEpEnOdEysyqQA9acE5KgvXXz/vQdGC5EsVkVhaNll+tNCLidUlbAqcBL0g6HRixoFUqiW6kylxLk/7/fA08EcGn5Y65nHKzVFuQOmYvAkwCXgdeWNDhUklLAZcD6wJ7RsRzZQ7XbMFSBcnNSS0SpgGfAaOJmF78LbU8cDzwE+ApUqn/x7y6bWZVpjupzHmjhGrMGBg3Dk49FQYPhh12gO22g3/8I+99ZpNndavqSHnHdkRU9djOEm/zawWSNgSuBz4Bjo6IsY2vYS3gZ8AA0htQe0C5v3cGHiZVq3u8mirbSPQCDgNOBRbLfbsdMCv35yek0vK3RlDX+PnaDxhGmpk/KyKmtkbcZnmlbby7kiZJvg/MIL1Wg/Q7DXAFMIyID5t/W21C2sr3f8DNwCWuDGpm1UqiK2nSNG899A02gKFD02rU88/DF1/AtGlw1FENr5wSsNVoeOlF4A3SmdExVbNCn3r/NWtshwfkVcvJVCuR1BH4FWmm+WRgZEREbsXmt8AppNmKQsviQeoQ/jTwgwimlD/qhSOxNXA/6c2jexOXTgamkpr0vZyeq8WBS0l9cw6PiKfKHK5Z06QlgL8Da5JWVwuZRnq9nkLEZYVvp/bAXqQkahVgKHBNRHxTspjNzDIiMZZmbtF78km4/nq46qqGj8yqgxWOhM9XBdYC1s79OZNcYpX7mpNovRMRM0r0IxQvtW1p8diOiIof21ljTqZaWW4G+gbgTeh2LEz5DXAoTScb85pKetPYMoKKLYMssSPwV5q/PD/nDWU70PKkxqN3AL+MiEYrVmatKiX3/yFV0evUzGfVAb8j4vfz30o9gCNIs5VfkPpDjaqIAYCZWYlInAr8hjzjgA02gDffhHbtYOBAOO64VC59+vybpKcDV0Zw4vz3lUjb5eYkVnO+1gZWBD5knlUs5iZbX7bKlukU32UUObbDLS6qjpOpDEjqDJwNpxwHf+gMHTq38Bb1wMMR7FOG8BaaxOrAizQ9e1/A5Omw1mcw9rCIeKzUsZm1WPpgfBbYkOYnUnPUAz8iYpSklYETSInUaGBwRDxd0ljNzCqExBLAx0CXho9deGHa0texI/zrX3DCCfDOO41uMRXYIIK3m//vVGfS2ex5V7Hm/D2YfxVrztfbsRBnXfMEcQJwPs1PpOaoBx4moiLHdlaYk6mMSHSCmV9Bh/kSjkmT5r+ua1e47DI48UQaqge+G8Fr5YyzGBLXkvYHz7dXeuWV08+yxRZpb/Sdd8JJJ8GsWfNeNX0WzLgoovsvWjFks8KknYC7aTg50KlT+oXu2zc1S3nnHTjjDHjwwfkuq4dPu8MTkQ4fjwCGRsQHrRS9mVlmJC4jjQdaWkRiKmnSeO/SxCEBSzF/cjXn7ysBH9F4y+AYYFyLVrOkTsA4oFejxxZbDK69FnbZBb78Mn1e3HJLw6vqge8SUXFjOyvM1fyy8wPo0OgFOm/fhe7d4bPP4I478j6/I3AScHR5wiuORE+gH3kOnV52Wargs9xysOii8PDDaXl/6NB5r+rUHjr9VOLXEXjbk1WCU8k3w9ihA3z0USpD9eGHsMcecPvtaf/KB3Nzpdmw7LEw9jLoHRGTGt3HzKx2/YzUI+97QNdmPmca8C5pLFESuYRoXO7rX/M+ppQAzVnNWotUefiI3N/bS5o3uZrz97cjYlqef9W+FGo7NGxY2se4zDLQpw/cfz+89BK8Nl/eVJFjO2uaV6YyIvEfYJOmrjnsMDj7bFhttYKX1ANLRzC5xOEVTeI4UnW+RoPP116DU06Bv/0t/fOFF0LPnnDMMY1uMwk4IoK7yhut2QJIKwBvk2ebSl4vvQTnnAOjRn37rYDZgr8SsW9ZYjQzq2ASXYDbSKvzC9r6NpnUS3KPSmjUK2lJ8p/NWplUjXi+RGsaDO0EGzS6Ubdu8M03qXzhW7lCrTfcAJ98klao5lcPLE1ExYztrGlu2pudDRd0wYAB6bXWhBmkF3Yl2YECb5ZDhsDBB6eti8svD7vv3mhH1Bw9gC3LF6JZs21KmiVdsKWXhjXXhFdfne/bSu+zm5c+NDOzyhfBVNKKzYHAP0hb+OpJZ5hinn9+lrQlcLtKSKQAIuLLiHgiIq6NiNMiYp+IWIs0TtmDVCzrM2Az4HfKl0hB+myYOXNuIgVp8m299fJdXYljO2uCt/llIJ2XajqRXWmltHvoyCObvFWQGoZWksULPfD443D00TBxYtohdd11cPfdBe+zdBliM2upXhTokzKfDh3g5ptTbd8xY/JdUUQxFjOz2pDrj/k34G8SvUk99ZYkjYW+Av4ewRvZRdgyueqrc1ak7gXmnJeqJ9/4bpFF0uBnXhMmzH+2Y57bU3ljO2uCV6ayMXNBFxx6KDzxBLz/flNXje8FWz0iKSrlCx7YIV+kUlqFGjUqnQVbYol0FvOCCwr+cO61YJVgGjC7ySskuPHGtBf++OMLXVW6SlFmZlUsgvcjGBbBORGcHcEl1ZRINaHw2G7y5HSuYV49ezauOjbX1JJFZWXnZCoDEcyGppewDzssTXI3bdF6eHK1iFClfMEew4BZDSNdfPFUze/SS9OY8+uvYcSIdGY/j+mAq51ZJfiE1K2+sGuvTQeK998/bePIb1ypAzMzswoSUXhs9+abaQfD6qvP/d5GGzXaFp7TCfi0DBFamTiZys51FJit3mILWGGFglX85vV2BO+WOK6FNZw8Z0y++grefReOPRbat4devdKZsJdfznuP2cDIMsdp1hxPQxPNsS+/HNZZB/baC6YWnEicAlxehtjMzKyyjCDf2K6uLm3N+e1vUzGKLbeEffZJuxoae5uIShvbWROcTGXnUgpsHxowIL3mJjddx2USqWpeRYngBeD9fI/ttx/stht88QW8/TbMmAGDBuW9zVMRXpmyCpBmGv9EvoRqpZVSKco+fVIPg0mT0lf//g2vbA8scJ3ZzMyqXsGxHQMHpgpc48al/lLHHtuwLDpU6NjOmubS6BmSeBTYhuIKgUwAloloZqWxViTxI+AKWt79G9Is/n4R/L20UZkVKZXG/ZDm90iZ1zTgNiIGlDYoMzOrSNJoYFsWYmxH/h5WVqG8MpWtHwHjSZVbWqIe2LcSE6mckcBDNLU9Kr864AYnUlZRIr4kleuta+EzZ5LOXJ1Y8pjMzKxSHcpCjO2cSFUfJ1MZimAsaWXqC1JfgeaoA/pF8M9yxbWwcgU2+gOP0vyqfFOAO4ATyhWXWdEi7gB+RvMnCKaRVrO2JaIi+qWYmVkriCh6bEfEP8sVlpWPk6mM5cqBbgSMIpXCzDf7PSP32JOkZnb3tF6Excmtmu0NnEvqIZGv/mfkvv8pcApwRETjSoBmFSHiGmBP4CVSUpWvdN+U3GM3AJsQ8UnrBWhmZhUhosVjOyIqfmxn+fnMVAWRWAL4MWlL0ZKkg+sTgQeAP0fwdobhFU2iA6lB3yBgNaAbadD5Gulw/yO51Syz6iBtAJwMbAf0JFVvGkc6K3gzEQWbh5iZWRsiNTm2I6Iqx3Y2l5MpMzMzMzOzInibn5mZmZmZWRGcTJmZmZmZmRXByZSZmZmZmVkRnEyZmZmZmZkVwcmUmZmZmZlZEZxMmZmZmZmZFcHJlJmZmZmZWRGcTJmZmZmZmRXByZSZmZmZmVkRnEyZmZmZmZkVwcmUmZmZmZlZEZxMmZmZmZmZFcHJlJmZmZmZWRGcTJmZmZmZmRXByZSZmZmZmVkRnEyZmZmZmZkVwcmUmZmZmZlZEZxMmZmZmZmZFcHJlJmZmZmZWRGcTJmZmZmZmRXByZSZmZmZmVkRnEyZmZmZmZkVwcmUmZmZmZlZEZxMmZmZmZmZFcHJlJmZmZmZWRGcTJmZmZmZmRXByZSZmZmZmVkRnEyZmZmZmZkV4f8B/cKouf7+nE8AAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 1080x288 with 3 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Gnerate a connected graph with 10 vertices\n",
"n = 10\n",
"G = nx.Graph()\n",
"G.add_nodes_from([0,1,2,3,4,5,6,7,8,9])\n",
"G.add_edges_from([(0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,0)])\n",
" \n",
"k = 9 # Set qubit (vertex) limit\n",
"S = NaiveLGP(G,k) # Partition G into two subgrahs once\n",
"sep_node = list(set(S[0].nodes).intersection(set(S[1].nodes))) # Obtain seperation nodes of the partition\n",
"\n",
"# Show graph illustration\n",
"options = {\n",
" \"with_labels\": True,\n",
" \"font_color\": \"white\"\n",
"}\n",
"node_color0 = [\"red\" if i in sep_node else \"blue\" for i in range(n)]\n",
"node_color1 = [\"red\" if list(S[0].nodes)[i] in sep_node else \"blue\" for i in range(len(S[0].nodes))]\n",
"node_color2 = [\"red\" if list(S[1].nodes)[i] in sep_node else \"blue\" for i in range(len(S[1].nodes))]\n",
"\n",
"fig, ax = plt.subplots(1, 3, figsize=(15, 4))\n",
"for i, a in enumerate(ax):\n",
" a.axis('off')\n",
" a.margins(0.20)\n",
"nx.draw_networkx(G, pos=nx.circular_layout(G), ax=ax[0], **options, node_color=node_color0)\n",
"nx.draw_networkx(S[0], pos=nx.circular_layout(S[0]), ax=ax[1], **options, node_color=node_color1)\n",
"nx.draw_networkx(S[1], pos=nx.circular_layout(S[1]), ax=ax[2], **options, node_color=node_color2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that in our case, both subgraphs are under the qubit limit and can be directly solved by QAOA. But if the subgraph still exceeds the qubit limit, we will recursively do LGP through recursively doing DC-QAOA."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Graph Reconstruction (GR)\n",
"\n",
"Once QAOA is applied to partitioned subgraphs, we should combine the solutions for the parent graph. Note that since two partitioned subgraphs share some set of nodes, we need to make sure that the labeling sets which these nodes are in are consistent. For example, if in one subgraph, the shared nodes are all in $S_0$, while in the other subgraph, some of the shared nodes are in $S_0$ and some are in $S_1$. In this situation, corresponding solutions cannot be combined. So we provide several possible cuts for each partitioned subgraphs to avoid failure for the combination. "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T06:51:47.629119Z",
"start_time": "2021-05-11T06:51:47.585155Z"
}
},
"outputs": [],
"source": [
"def GR(str_cnt1, str_cnt2):\n",
" com_cnt = []\n",
" n = len(str_cnt1[0][0])\n",
" com_index = []\n",
" for i in range(n):\n",
" if str_cnt1[0][0][i] != \"x\" and str_cnt2[0][0][i] != \"x\":\n",
" com_index.append(i)\n",
" \n",
" for (str1, cnt1) in str_cnt1:\n",
" for (str2, cnt2) in str_cnt2:\n",
" # Check equality for each bit in common nodes\n",
" validity = [str1[i] == str2[i] for i in com_index]\n",
" if False not in validity:\n",
" com_str = [[0]] * n\n",
" for i in range(n):\n",
" if str1[i] != \"x\":\n",
" com_str[i] = str(str1[i])\n",
" else:\n",
" com_str[i] = str(str2[i])\n",
" com_cnt.append((\"\".join(com_str), min(cnt1, cnt2)))\n",
"\n",
" # Sort string-count map by counts in reverse order\n",
" com_cnt.sort(key=lambda tup:tup[1])\n",
" return com_cnt[::-1]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We still take the above example for illustration. For two subgraphs partitioned above, we apply QAOA to find their approximate max cuts and then use GR policy to form the max cut for the original graph. The code presented below has achieved this. Note that there is a parameter $t$ controlling how many possible cuts are kept, and if this $t$ is larger than $2^k$, all cuts are provided and the combination can definitely happen. "
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T06:52:48.693469Z",
"start_time": "2021-05-11T06:51:47.651060Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Max cut for the first partitioned subgraph: \n",
"{'010xxxxxxx': 0.49999449162430293, '101xxxxxxx': 0.49999449162430293, '111xxxxxxx': 2.420265869021529e-06, '000xxxxxxx': 2.42026586902126e-06, '001xxxxxxx': 1.5440549138418965e-06, '011xxxxxxx': 1.544054913841822e-06, '100xxxxxxx': 1.544054913841805e-06, '110xxxxxxx': 1.5440549138414785e-06}\n",
"Max cut for the second partitioned subgraph: \n",
"{'1x10101010': 0.14011845299520345, '0x01010101': 0.14011845299520342, '1x01010010': 0.04249785377879293, '0x10101101': 0.04249785377879292, '1x01011010': 0.0424978537787929, '0x10100101': 0.042497853778792886, '0x10101001': 0.036328002709709185, '1x01010110': 0.03632800270970918, '0x10110101': 0.03632800270970918, '1x01001010': 0.036328002709709165}\n",
"Combined max cut for the original graph: \n",
"{'1010101010': 0.14011845299520345, '0101010101': 0.14011845299520342, '1110101010': 2.420265869021529e-06, '0001010101': 2.42026586902126e-06, '0010110101': 1.5440549138418965e-06, '0010101001': 1.5440549138418965e-06, '0010100101': 1.5440549138418965e-06, '0010101101': 1.5440549138418965e-06, '0110110101': 1.544054913841822e-06, '0110101001': 1.544054913841822e-06}\n"
]
}
],
"source": [
"# We use direct QAOA to compute approximate max cuts for two subgraphs\n",
"# In the next section, we will compute these using DC-QAOA because subgraphs might also exceed the qubit limit\n",
"import paddle\n",
"from paddle_quantum.QAOA.maxcut import find_cut\n",
"\n",
"# Set QAOA parameters\n",
"p = 3 # Number of layers of QAOA circuit\n",
"ITR = 100 # Iterations of the training network of QAOA\n",
"LR = 0.5 # Learning rate in the training network of QAOA\n",
"# Set graph reconstruction parameter\n",
"t = 10 # Number of partition strings kept after graph reconstruction \n",
"paddle.seed(999) # Fix the seed\n",
"\n",
"# Start graph reconstruction procedure\n",
"S_str_cnt = []\n",
"for si in S:\n",
" siv = list(si.nodes)\n",
" # Compute the subgraph's maxcut\n",
" tmp, si_str_cnt_relabeled = find_cut(si, p, ITR, LR)\n",
" # Make the subgraph's maxcut match the original graph by relabeling \n",
" si_str_cnt = []\n",
" for str_relabeled in si_str_cnt_relabeled:\n",
" strr = \"\"\n",
" for i in range(len(G.nodes)):\n",
" if i in siv:\n",
" strr += str_relabeled[siv.index(i)]\n",
" else:\n",
" strr += \"x\"\n",
" si_str_cnt.append((strr, si_str_cnt_relabeled[str_relabeled]))\n",
" si_str_cnt.sort(key=lambda tup:tup[1])\n",
" S_str_cnt.append(si_str_cnt[::-1][:t])\n",
"\n",
"# Once we have already obatined max cut strings for two paritions, we perform the graph reconstruction (GR)\n",
"print(\"Max cut for the first partitioned subgraph: \\n\" + str(dict(S_str_cnt[0])))\n",
"print(\"Max cut for the second partitioned subgraph: \\n\" + str(dict(S_str_cnt[1])))\n",
"out_cnt = GR(S_str_cnt[0], S_str_cnt[1])\n",
"print(\"Combined max cut for the original graph: \\n\" + str(dict(out_cnt[:t])))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The top several possible max cuts for the first subgraph include {'010xxxxxxx','101xxxxxxx'} and those for the second subgraph include {'1x10101010','0x01010101'}, where 'x' indicates those missing nodes in the subgraph. Shared nodes $0$ and $2$ are all '0's in the first possibility of the first subgraph, i.e. '010xxxxxxx', while they are all '1's in the first possibility of the second subgraph, i.e. '1x10101010', so they cannot combine. (Note that although we can flip 0s and 1s in this situation by symmetry, it is not necessary). We then try to combine '010xxxxxxx' (first possibility of the first subgraph) and '0x01010101' (second possibility of the second subgraph). It is clear that the shared nodes $0$ and $2$ are all '0's in both subgraphs as shown below in the left and middle figure, so we combine these two max cuts and get '0101010101' for the original cycle of six as shown below in the right.\n",
"\n",
"Graph illustration is shown below. The left and middle subgraphs are subgraphs with approximate max cuts, where red and blue nodes represent $S_0$ and $S_1$ and dashed lines represent cuts."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T06:52:49.021611Z",
"start_time": "2021-05-11T06:52:48.704511Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 1080x288 with 3 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Computed max cut for two subgraphs\n",
"strr1 = '010xxxxxxx'\n",
"strr2 = '0x01010101' \n",
"strr = '0101010101'\n",
"\n",
"# Show graph illustration\n",
"options0 = {\n",
" \"node_color\": [\"red\" if strr1[i] == '0' else \"blue\" for i in S[0].nodes],\n",
" \"style\": [\"solid\" if strr1[u] == strr1[v] else \"dashed\" for (u, v) in list(S[0].edges)]\n",
"}\n",
"options1 = {\n",
" \"node_color\": [\"red\" if strr2[i] == '0' else \"blue\" for i in S[1].nodes],\n",
" \"style\": [\"solid\" if strr2[u] == strr2[v] else \"dashed\" for (u, v) in list(S[1].edges)]\n",
"}\n",
"options2 = {\n",
" \"node_color\": [\"red\" if strr[i] == '0' else \"blue\" for i in range(n)],\n",
" \"style\": [\"solid\" if strr[u] == strr[v] else \"dashed\" for (u, v) in list(G.edges)]\n",
"}\n",
"\n",
"fig, ax = plt.subplots(1, 3, figsize=(15,4))\n",
"for i, a in enumerate(ax):\n",
" a.axis('off')\n",
" a.margins(0.20)\n",
"nx.draw_networkx(S[0], pos=nx.circular_layout(S[0]), ax=ax[0], **options, **options0)\n",
"nx.draw_networkx(S[1], pos=nx.circular_layout(S[1]), ax=ax[1], **options, **options1)\n",
"nx.draw_networkx(G, pos=nx.circular_layout(G), ax=ax[2], **options, **options2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### DC-QAOA\n",
"\n",
"To find the max cut for a large graph with the number of vertices exceeding limits, DC-QAOA recursively divides it through LGP policy and conquers sub-solutions with GR policy described above. It adopts the divide-and-conquer paradigm to deal with the max-cut problem for large-scale graphs. \n",
"\n",
"The input graph is separated into exactly two subgraphs through LGP policy if the vertex size is larger than the qubit limit. Otherwise, its max cut would be directly calculated by QAOA. Each subgraph will recursively call DC-QAOA until its max-cut solution are returned, i.e. at some step, the vertex size of the subgraph is under the limit and can be directly processed by QAOA and returned values would be combined and then be given to the upper layer. \n",
"\n",
"The code below provides the way to run DC-QAOA and LGP and GR policies are both applied in the `DC_QAOA` function. Note that QAOA would return a series of possible cuts, sorted by frequency count. "
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T06:54:04.788730Z",
"start_time": "2021-05-11T06:52:49.025846Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"First t possible approximate maxcut for graph G: {'1010101010': 938, '0101010101': 878, '0110101001': 160, '0110101011': 160, '1001010110': 152, '1001010100': 152, '1001010010': 145, '1101010010': 137, '1101010110': 137, '1101010100': 137}\n",
"Max cut found by DC-QAOA algorithms: 1010101010\n"
]
}
],
"source": [
"def DC_QAOA(g, p, t, s, k, ITR, LR):\n",
" if len(g.nodes) > k:\n",
" # get exactly two subgraphs with LGP policy\n",
" S = NaiveLGP(g, k)\n",
"\n",
" S_str_cnt = []\n",
" for si in S:\n",
" siv = list(si.nodes)\n",
" # Compute the subgraph's maxcut recursively\n",
" _, si_str_cnt_relabeled = DC_QAOA(si, p, t, s, k, ITR, LR)\n",
" # refilling str_cnt1 and str_cnt2\n",
" si_str_cnt = []\n",
" for str_relabeled in si_str_cnt_relabeled:\n",
" strr = \"\"\n",
" for v in g.nodes:\n",
" if v in siv:\n",
" strr += str_relabeled[siv.index(v)]\n",
" else:\n",
" strr += \"x\"\n",
" si_str_cnt.append((strr, si_str_cnt_relabeled[str_relabeled]))\n",
" si_str_cnt.sort(key = lambda tup:tup[1])\n",
" S_str_cnt.append(si_str_cnt[::-1][:t])\n",
" # Reconstruct string-count map with GR policy\n",
" out_cnt = GR(S_str_cnt[0], S_str_cnt[1])\n",
" else:\n",
" if len(g.nodes) == 1:\n",
" return [(\"0\", 99999), (\"1\", 99999)]\n",
" _, out_cnt = find_cut(g, p, ITR, LR, shots=3000)\n",
" # Transform {str:cnt} dictionary into [(st, cnt)] tuple list\n",
" out_cnt = [(k, v) for k, v in out_cnt.items()]\n",
" # Sort string-count map by counts in reverse order\n",
" out_cnt.sort(key=lambda tup:tup[1])\n",
" out_cnt = out_cnt[::-1]\n",
"\n",
" # retain only top t (str,cnt) pairs by sorted order\n",
" out_cnt = out_cnt[:t]\n",
" # resacle total numer of counts to s or around\n",
" cnt_sum = sum(cnt for (str, cnt) in out_cnt)\n",
" out_cnt = [(k, int(s * v / cnt_sum)) for (k, v) in out_cnt]\n",
"\n",
" return out_cnt[0][0], dict(out_cnt)\n",
" \n",
"# Set QAOA parameters\n",
"p = 2 # Number of layers of QAOA circuit\n",
"ITR = 100 # Iterations of the training network of QAOA\n",
"LR = 0.5 # Learning rate in the training network of QAOA\n",
"\n",
"#Set DC-QAOA parameters\n",
"s = 3000 # Multiplier to make frequency bigger\n",
"t = 10 # Number of partition strings kept after graph reconstruction \n",
"k = 5 # Maximum qubits/vertices limit\n",
"\n",
"# Using DC-QAOA\n",
"max_cut, out_cnt = DC_QAOA(G, p, t, s, k, ITR, LR)\n",
"print(\"First t possible approximate maxcut for graph G: \" + str(out_cnt))\n",
"print(\"Max cut found by DC-QAOA algorithms: \" + str(max_cut))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Applicability"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**DC-QAOA described above can approximate max cut for a graph if and only if its and one family of its recursive children's pseudo-connectivities are all smaller than $k$, where $k$ is the qubit limit (vertex limit).**\n",
"\n",
"The pseudo-connectivity here is defined as the minimum number of vertices that need to be removed to separate the remaining vertices into exactly two isolated subgraphs. A graph's recursive children mean its two partitioned subgraphs and then their partitioned sub-subgraphs until some are smaller or equal to the qubit limit. \n",
"\n",
"Cycles are applicable examples if the qubit limit is larger than $1$. Its pseudo-connectivity is $2$ as removing two vertices can partition cycles into two paths. For the example of $C_6$ (cycle of six) with qubit limit 4, partitions described above are $P_5$ (path of five) and $P_2$. $P_2$ is under the qubit limit, and $P_5$ can be partitioned into $P'_4$ and $P'_2$ and thus have pseudo-connectivity $1$. Then $P'_4$ and $P'_2$ are under the qubit limit. So this family of the $C_6$ has all its recursive children's ($C_6$, $P_5$) pseudo-connectivities smaller than $4$. \n",
"\n",
"Non applicable examples include complete graphs with $n$ larger than $k$, because no matter how you remove vertices, the rest graph is still connected. Another example for which different qubit limits influence its applicability is shown below. \n",
"\n",
"The left graph is the original graph. If the qubit limit is $2$, then the number of separation nodes can only be $1$ and no vertice could partition the graph into $2$. If we remove vertex $4$ (as shown in the middle), the graph will be partitioned into three while others will leave a connected graph. Besides, the graph's pseudo-connectivity is $2$, not smaller than $k=2$, and so DC-QAOA fails in this case. However, if the qubit limit is $3$, then its pseudo-connectivity is under $k$ and we can remove vertex $0$ and $3$ as shown in the right. Then the rest are two components, with one under the qubit limit and one can be partitioned into two further (by removing vertex $4$ and with pseudo-connectivity being $1 < k$). So DC-QAOA succeeds here. \n",
"\n",
"![limitations-connectivity](./figures/dcqaoa-fig-applicability_example.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"People can try the example shown above by adjusting the parameter $k$ in the code below."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T06:54:45.016920Z",
"start_time": "2021-05-11T06:54:04.825816Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"First t possible approximate maxcut for graph G: {'00001': 532, '00101': 501, '11110': 496, '01001': 496, '10110': 492, '11010': 483}\n"
]
}
],
"source": [
"G = nx.Graph()\n",
"G.add_nodes_from([0, 1, 2, 3, 4])\n",
"G.add_edges_from([(0, 4), (1, 2), (1, 4), (2, 4), (3, 4)])\n",
"k = 3\n",
"_, out_cnt = DC_QAOA(G, p, t, s, k, ITR, LR)\n",
"print(\"First t possible approximate maxcut for graph G: \" + str(dict(out_cnt)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Performance\n",
"\n",
"We have compared DC-QAOA with classical max-cut approximation algorithms to test its performance. We provide the performance below of finding max-cut by DC-QAOA and the upper bound for max cut provided by SDP. We take five random graphs of 10 vertices as an example to show the performance (qubit limit for DC-QAOA is set to be 5). \n",
"\n",
"In order to run the following test, users need to install cvxpy: `pip install cvxpy`. **Windows users may encounter an error at runtime if they install cvxpy using pip. Instead, we recommend Windows users to create a new conda environment and install cvxpy with conda.** For more details please see [https://www.cvxpy.org/install/](https://www.cvxpy.org/install/)."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T06:54:47.679276Z",
"start_time": "2021-05-11T06:54:47.341106Z"
}
},
"outputs": [],
"source": [
"import cvxpy as cvx\n",
"import networkx as nx\n",
"\n",
"def sdp_solver(G):\n",
" \"\"\"\n",
" Use SDP to find the upper bound for the max-cut problem.\n",
" \"\"\"\n",
" n = len(G)\n",
" adj_mat = nx.adjacency_matrix(G).toarray()\n",
" Y = cvx.Variable((n, n), PSD=True)\n",
" cut_size = 0.25 * cvx.sum(cvx.multiply(adj_mat, 1 - Y))\n",
" problem = cvx.Problem(cvx.Maximize(cut_size), [cvx.diag(Y) == 1])\n",
" opt_val = problem.solve(cvx.SCS)\n",
"\n",
" return opt_val"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T07:02:35.277145Z",
"start_time": "2021-05-11T06:54:47.682769Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Number of node = 10\n",
"Node = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
"\n",
"Random graph 1\n",
"Edges = [(0, 2), (0, 6), (0, 7), (0, 8), (1, 3), (1, 5), (1, 6), (1, 8), (1, 9), (2, 3), (2, 4), (2, 6), (2, 8), (2, 9), (3, 4), (3, 6), (3, 7), (3, 8), (3, 9), (4, 9), (5, 8), (7, 9), (8, 9)]\n",
"SDP upper bound: 17.750789460578076\n",
"DC-QAOA node partition: 1001011001, max cut = 17.0\n",
"\n",
"Random graph 2\n",
"Edges = [(0, 1), (0, 3), (0, 6), (1, 2), (1, 3), (2, 5), (2, 6), (2, 7), (3, 5), (3, 6), (3, 8), (3, 9), (4, 6), (4, 7), (4, 8), (4, 9), (5, 7), (5, 8), (6, 7), (6, 8), (7, 9)]\n",
"SDP upper bound: 16.64755118085844\n",
"DC-QAOA node partition: 1100111001, max cut = 15.0\n",
"\n",
"Random graph 3\n",
"Edges = [(0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (2, 3), (2, 4), (2, 6), (2, 7), (2, 8), (4, 5), (4, 7), (4, 9), (5, 7), (5, 8), (5, 9), (6, 7), (7, 8), (8, 9)]\n",
"SDP upper bound: 19.402766322145684\n",
"DC-QAOA node partition: 1101100010, max cut = 18.0\n",
"\n",
"Random graph 4\n",
"Edges = [(0, 1), (0, 2), (0, 5), (0, 6), (0, 7), (0, 9), (1, 5), (1, 6), (1, 7), (1, 9), (2, 3), (2, 6), (2, 8), (3, 5), (3, 6), (3, 8), (3, 9), (4, 5), (4, 6), (4, 7), (4, 9), (5, 6), (5, 7), (5, 8), (6, 7), (6, 8), (7, 8)]\n",
"SDP upper bound: 20.999869854784496\n",
"DC-QAOA node partition: 0010011011, max cut = 18.0\n",
"\n",
"Random graph 5\n",
"Edges = [(0, 1), (0, 4), (0, 7), (1, 2), (1, 3), (1, 6), (1, 7), (1, 8), (1, 9), (2, 4), (2, 7), (2, 9), (3, 7), (3, 9), (4, 5), (4, 6), (4, 8), (5, 6), (5, 7), (5, 8), (6, 7), (6, 8), (6, 9), (7, 9), (8, 9)]\n",
"SDP upper bound: 19.454398132157152\n",
"DC-QAOA node partition: 1011011001, max cut = 18.0\n"
]
}
],
"source": [
"n = 10\n",
"iter = 5\n",
"print(\"Number of node = \" + str(n))\n",
"print(\"Node = \" + str([i for i in range(n)]))\n",
"\n",
"value_dc_qaoa_ls = []\n",
"ubound_sdp_ls = []\n",
"for i in range(iter):\n",
" print(\"\\nRandom graph \" + str(i+1))\n",
" # Generate random graph\n",
" G = nx.erdos_renyi_graph(n, 0.1, 100 * i, directed=False)\n",
" while nx.is_connected(G) == False:\n",
" G = nx.erdos_renyi_graph(n, 0.5, directed=False)\n",
" print(\"Edges = \" + str(list(G.edges)))\n",
" # SDP upper bound calculation \n",
" ubound_sdp = sdp_solver(G)\n",
" ubound_sdp_ls.append(ubound_sdp)\n",
" print(\"SDP upper bound: \" + str(ubound_sdp))\n",
"\n",
" # QAOA parameters\n",
" p = 2 # Number of layers of QAOA circuit\n",
" ITR = 100 # Iterations of the training network of QAOA\n",
" LR = 0.5 # Learning rate in the training network of QAOA\n",
" # DC-QAOA parameters\n",
" s = 3000 # Multiplier to make frequency bigger\n",
" t = 20 # Number of partition strings kept after graph reconstruction \n",
" k = 5 # Maximum qubits/vertices limit\n",
"\n",
" try:\n",
" cut_dc_qaoa, out_cnt = DC_QAOA(G, p, t, s, k, ITR, LR)\n",
" cut_dc_qaoa1 = [\"solid\" if cut_dc_qaoa[u] == cut_dc_qaoa[v] else \"dashed\" for (u, v) in list(G.edges)]\n",
" value_dc_qaoa = cut_dc_qaoa1.count(\"dashed\")\n",
" value_dc_qaoa_ls.append(value_dc_qaoa)\n",
" print(\"DC-QAOA node partition: \" + str(cut_dc_qaoa) + \", max cut = \" + str(float(value_dc_qaoa))) \n",
" except Exception as e:\n",
" value_dc_qaoa = 0\n",
" value_dc_qaoa_ls.append(value_dc_qaoa)\n",
" print(\"DC-QAOA fails with error message '\" + str(e) + \"'\")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-11T07:02:35.547590Z",
"start_time": "2021-05-11T07:02:35.280626Z"
}
},
"outputs": [
{
"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": [
"import matplotlib.pyplot as plt\n",
"\n",
"plt.plot(value_dc_qaoa_ls, label=\"DC-QAOA\")\n",
"plt.plot(ubound_sdp_ls, label=\"SDP upper bound\", linestyle=\"--\")\n",
"plt.title('Max-Cut Performancce')\n",
"plt.xlabel('Random Graph')\n",
"plt.ylabel('Calculated Optimal Max Cut')\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From the line graph above, we have verified that max-cut generated by DC-QAOA is under and close to this bound.\n",
"\n",
"## Applications\n",
"\n",
"The Max-Cut problem belongs to quadratic unconstrained binary optimization (QUBO), which has a wide range of applications, from finding ground states for the spin glass problem to modeling NP-hard problems [5]. The Max-Cut problem itself inherits widespread usefulness.\n",
"\n",
"It is extensively related to various fields, including VLSI circuit design, statistical physics. Both the problem of minimizing the number of vias subject to pin preassignments and layer preferences and the problem of finding ground states of spin glasses with exterior magnetic field in the Ising model can be reduced to the Max-Cut problem [6]. \n",
"\n",
"Also importantly, the Max-Cut problem provides a prototypical testbed for algorithmic techniques that can be applied to many interesting problems. For example, SDP relaxation of the Max-Cut problem is adopted in designing data clustering algorithms [7] and addressing the phase retrieval problem [8, 9].\n",
"\n",
"More detailed investigations on the Max-Cut problem can be found in [10-12]."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## References\n",
"\n",
"[1] Akshay, V., et al. \"Reachability deficits in quantum approximate optimization.\" [Physical Review Letters 124.9 (2020): 090504.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.124.090504)\n",
"\n",
"[2] Li, Junde, Mahabubul Alam, and Swaroop Ghosh. \"Large-scale Quantum Approximate Optimization via Divide-and-Conquer.\" [arXiv preprint arXiv:2102.13288 (2021).](https://arxiv.org/abs/2101.03717)\n",
"\n",
"[3] Goemans, Michel X., and David P. Williamson. \"Improved approximation algorithms for maximum cut and satisfiability problems using semidefinite programming.\" [Journal of the ACM (JACM) 42.6 (1995): 1115-1145.](http://www-math.mit.edu/~goemans/PAPERS/maxcut-jacm.pdf)\n",
"\n",
"[4] Burer, Samuel, and Renato DC Monteiro. \"Local minima and convergence in low-rank semidefinite programming.\" [Mathematical Programming 103.3 (2005): 427-444.](https://link.springer.com/article/10.1007/s10107-004-0564-1)\n",
"\n",
"[5] Kochenberger, Gary, et al. \"The unconstrained binary quadratic programming problem: a survey.\" [Journal of Combinatorial Optimization 28.1 (2014): 58-81.](https://link.springer.com/article/10.1007/s10878-014-9734-0)\n",
"\n",
"[6] Barahona, Francisco, et al. \"An application of combinatorial optimization to statistical physics and circuit layout design.\" [Operations Research 36.3 (1988): 493-513.](https://www.jstor.org/stable/170992?seq=1)\n",
"\n",
"[7] Poland, Jan, and Thomas Zeugmann. \"Clustering pairwise distances with missing data: Maximum cuts versus normalized cuts.\" [International Conference on Discovery Science. Springer, Berlin, Heidelberg, 2006.](https://link.springer.com/chapter/10.1007/11893318_21)\n",
"\n",
"[8] Candes, Emmanuel J., et al. \"Phase retrieval via matrix completion.\" [SIAM review 57.2 (2015): 225-251.](https://epubs.siam.org/doi/10.1137/110848074)\n",
"\n",
"[9] Waldspurger, Irene, Alexandre d’Aspremont, and Stéphane Mallat. \"Phase recovery, maxcut and complex semidefinite programming.\" [Mathematical Programming 149.1 (2015): 47-81.](https://link.springer.com/article/10.1007/s10107-013-0738-9)\n",
"\n",
"[10] Deza, Michel, and Monique Laurent. \"Applications of cut polyhedra—I.\" [Journal of Computational and Applied Mathematics 55.2 (1994): 191-216.](https://www.sciencedirect.com/science/article/pii/0377042794900205)\n",
"\n",
"[11] Deza, Michel, and Monique Laurent. \"Applications of cut polyhedra—II.\" [Journal of Computational and Applied Mathematics 55.2 (1994): 217-247.](https://www.sciencedirect.com/science/article/pii/0377042794900213)\n",
"\n",
"[12] Poljak, Svatopluk, and Zsolt Tuza. \"Maximum cuts and largest bipartite subgraphs.\" [DIMACS Series 20 (1995): 181-244.](https://arxiv.org/pdf/1810.12144.pdf)"
]
}
],
"metadata": {
"celltoolbar": "Raw Cell Format",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-06T07:10:17.389768Z",
"start_time": "2021-01-06T07:10:17.379639Z"
}
},
"source": [
"# Quantum Approximate Optimization Algorithm\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"Quantum Approximate Optimization Algorithm (QAOA) is a quantum algorithm that can run on recent Noisy Intermediate-Scale Quantum (NISQ) devices and has a wide range of applications. QAOA was proposed by Edward Farhi et al. in 2014 [1], and its purpose is to solve combinatorial optimization problems approximately."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Combinatorial optimization problem\n",
"\n",
"In applied mathematics and theoretical computer science, combinatorial optimization is a type of topic that finds the optimal object in a limited set of objects. In simple terms, the combinatorial optimization problem means that all solutions of the problem are composed of discrete variables, and the optimal solution is to be found in the discrete solution set. Combinatorial optimization problems involve a wide range of areas and are common in real life, such as the design of aircraft routes and the planning of express delivery routes.\n",
"\n",
"Specifically, a combinatorial optimization problem can be described by $n$ bits and $m$ clauses. The value of each bit is $0$ or $1$, and we use $z_j$ to denote the value of the $j$th bit. Therefore, the value of these $n$ bits can be represented by the bit string $z=z_1z_2\\dots z_n$. Each clause is a restriction on some bits. For example, a clause can require the value of the $2$nd bit to be $0$, or it can require the value of the $3$rd bit and the $5$th bit to be the same. For the $j$th clause, we define a function\n",
"\n",
"$$\n",
"C_j(z)=\n",
"\\begin{cases}\n",
"1 & \\text{If the value $z$ of $n$ bits satisfies the condition indicated by clause $j$}\\\\\n",
"0 & \\text{if the value $z$ of $n$ bits does not satisfy the condition indicated by clause $j$}\n",
"\\end{cases}.\n",
"\\tag{1}\n",
"$$\n",
"\n",
"For example, if the first clause requires the value of the second bit to be 0, then we have $C_1(z_10z_3\\dots z_n)=1$ and $C_1(z_11z_3\\dots z_n)=0$.\n",
"# QAOA 求解最大割问题\n",
"\n",
"From the definition of $C_j$ in equation (1), we can define the objective function of the combinatorial optimization problem\n",
"\n",
"$$\n",
"C(z)=\\sum_{j=1}^m w_jC_j(z),\n",
"\\tag{2}\n",
"$$\n",
"\n",
"where $w_j$ is the weight of the $j$th clause. The combinatorial optimization problem is to find a value $z$ that maximizes the value of the objective function $C(z)$, namely\n",
"\n",
"$$\n",
"\\underset{z}{\\operatorname{argmax}} C(z).\n",
"\\tag{3}\n",
"$$\n"
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Quantum approximate optimization algorithm\n",
"\n",
"Many combinatorial optimization problems are NP-complete or even NP-hard problems, which means that computers may not be able to solve such problems efficiently. An alternative is to find the approximate optimal solution to such problems, and this task can usually be completed efficiently. QAOA is a quantum algorithm that can find an approximate optimal solution to a combinatorial optimization problem.\n",
"\n",
"#### Encoding combination optimization problem\n",
"\n",
"For the above combinatorial optimization problem, there are $n$ bits and $m$ clauses. The QAOA algorithm transforms this problem into an optimization problem on an $n$-qubit system. Each computational basis state $|z\\rangle \\in \\{0,1\\}^n$ of the quantum system corresponds to a value $z$ of $n$ bits in the original problem. At the same time, for the $j$th clause in the original problem, we define a diagonal Hamiltonian $H_{C_j}$ satisfying\n",
"\n",
"$$\n",
"H_{C_j}|z\\rangle = C_j(z)|z\\rangle.\n",
"\\tag{4}\n",
"$$\n",
"\n",
"Specifically, we can construct the Hamiltonian $H_{C_j}$ through the following equation:\n",
"\n",
"$$\n",
"H_{C_j} = \\sum_{z\\in\\{0,1\\}^n} C_j(z)|z\\rangle\\langle z|.\n",
"\\tag{5}\n",
"$$\n",
"\n",
"For example, assuming that $z^{(1)}$ and $z^{(2)}$ are the values ​​satisfying the $j$th clause, then we can define\n",
"\n",
"$$\n",
"H_{C_j} = |z^{(1)}\\rangle\\langle z^{(1)}| + |z^{(2)}\\rangle\\langle z^{(2)}|.\n",
"\\tag{6}\n",
"$$\n",
"\n",
"Therefore, QAOA encodes the objective function $C$ of the combinatorial optimization problem into the Hamiltonian $H_C$ on a system with $n$ qubits, where\n",
"\n",
"$$\n",
"H_C = \\sum_{j=1}^m w_jH_{C_j},\n",
"\\tag{7}\n",
"$$\n",
"\n",
"and\n",
"\n",
"$$\n",
"H_C|z\\rangle = \\sum_{j=1}^m w_jH_{C_j}|z\\rangle = \\sum_{j=1}^m w_jC_j(z)|z\\rangle = C(z)|z\\rangle .\n",
"\\tag{8}\n",
"$$\n",
"\n",
"It is worth noting that if an optimal solution to the original problem is $z_\\text{opt}$, then we have\n",
"\n",
"$$\n",
"\\langle z_\\text{opt}|H_C|z_\\text{opt}\\rangle = \\langle z_\\text{opt}|C(z_\\text{opt})|z_\\text{opt}\\rangle = C( z_\\text{opt})\\langle z_\\text{opt}|z_\\text{opt}\\rangle = C(z_\\text{opt}).\n",
"\\tag{9}\n",
"$$\n",
"\n",
"Therefore, an optimal solution of the original combinatorial optimization problem is an eigenstate with the largest eigenvalue of the Hamiltonian $H_C$. In addition, for any quantum state $|\\psi\\rangle$,\n",
"\n",
"$$\n",
"\\langle\\psi|H_C|\\psi\\rangle \\leq C(z_\\text{opt}),\n",
"\\tag{10}\n",
"$$\n",
"\n",
"and the equation takes the equal sign if and only if $|\\psi\\rangle$ is a superposition state of optimal solutions. It can be obtained from equation (9) and equation (10) that\n",
"\n",
"$$\n",
"\\max_{|\\psi\\rangle} \\langle\\psi|H_C|\\psi\\rangle = C(z_\\text{opt}),\n",
"\\tag{11}\n",
"$$\n",
"\n",
"and finding the optimal solution of the original combinatorial optimization problem is equivalent to finding an eigenstate with the largest eigenvalue of the Hamiltonian $H_C$, that is, finding a quantum state $|\\psi\\rangle$ such that\n",
"\n",
"$$\n",
"H_c|\\psi\\rangle = C(z_\\text{opt})|\\psi\\rangle.\n",
"\\tag{12}\n",
"$$\n",
"\n",
"When we find such a quantum state $|\\psi\\rangle$, it is probably not a computational basis state, but a superposition of several computational basis states, each of which is an optimal solution of the original combinatorial optimization problem. Therefore, we can obtain an optimal solution to the original combinatorial optimization problem by performing computational basis measurements on $|\\psi\\rangle$.\n",
"\n",
"#### Finding an approximate optimal solution\n",
"\n",
"Although it is relatively simple to encode the objective function of the combinatorial optimization problem to be solved into the Hamiltonian $H_C$ of a quantum system, finding the quantum state $|\\psi\\rangle$ representing an optimal solution from the huge Hilbert space according to equation (11) is not easy. In order to find such a quantum state, we need another Hamiltonian\n",
"\n",
"$$\n",
"H_B = \\sum_{j=1}^n X_j,\n",
"\\tag{13}\n",
"$$\n",
"\n",
"where $X_j$ represents the Pauli $X$ gate acting on the $j$th qubit. The two eigenstates of Pauli $X$ gate are $|+\\rangle$ and $|-\\rangle$, and their corresponding eigenvalues ​​are $1$ and $-1$, respectively:\n",
"\n",
"$$\n",
"\\begin{align}\n",
"X|+\\rangle &=\n",
"\\begin{bmatrix}\n",
"0&1\\\\1&0\n",
"\\end{bmatrix}\n",
"\\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\1\n",
"\\end{bmatrix}\n",
"= \\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\1\n",
"\\end{bmatrix}\n",
"= |+\\rangle,\\tag{14}\\\\\n",
"X|-\\rangle &=\n",
"\\begin{bmatrix}\n",
"0&1\\\\1&0\n",
"\\end{bmatrix}\n",
"\\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\-1\n",
"\\end{bmatrix}\n",
"= \\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"-1\\\\1\n",
"\\end{bmatrix}\n",
"= -|-\\rangle.\\tag{15}\n",
"\\end{align}\n",
"$$\n",
"\n",
"Therefore, the eigenstate with the largest eigenvalue of $H_B$ is\n",
"\n",
"$$\n",
"|s\\rangle \\equiv \\underbrace{|+\\rangle\\otimes\\cdots\\otimes|+\\rangle}_\\text{$n$ terms} = |+\\rangle^{\\otimes n }.\n",
"\\tag{16}\n",
"$$\n",
"\n",
"We will use this quantum state $|s\\rangle$ as the initial state for the algorithm. After constructing the Hamiltonian $H_C$ and $H_B$, we can start to find an approximate optimal solution to the original combinatorial optimization problem. According to the Hamiltonian $H_C$ and $H_B$, respectively define the unitary transformation\n",
"\n",
"$$\n",
"U_C(\\gamma) = e^{-i\\gamma H_C}\n",
"\\tag{17}\n",
"$$\n",
"\n",
"and unitary transformation\n",
"\n",
"$$\n",
"U_B(\\beta) = e^{-i\\beta H_B},\n",
"\\tag{18}\n",
"$$\n",
"## 概览\n",
"\n",
"where $\\gamma$ and $\\beta$ are adjustable real parameters. Given any integer $p\\geq1$ and the parameters $\\vec{\\gamma}=(\\gamma_1,\\dots,\\gamma_p)$ and $\\vec{\\beta}=(\\beta_1,\\dots,\\beta_p) $, we define\n",
"在[量子近似优化算法教程](./QAOA_CN.ipynb)中,我们介绍了如何将经典的组合优化问题编码为量子优化问题,并用量子近似优化算法 [1](quantum approximate optimization algorithm, QAOA)求解。在本教程中,我们将以最大割问题为例来进一步阐述 QAOA。\n",
"\n",
"$$\n",
"|\\vec{\\gamma},\\vec{\\beta}\\rangle = U_B(\\beta_p)U_C(\\gamma_p)\\cdots U_B(\\beta_1)U_C(\\gamma_1)|s\\rangle.\n",
"\\tag{19}\n",
"$$\n",
"### 最大割问题\n",
"\n",
"It can be seen that the integer $p$ represents the number of layers of $U_C, U_B$, that is, the $U_C$ and $U_B$ are alternately applied to the initial state $|s\\rangle$ $p$ times. Let us denote $F_p(\\vec{\\gamma},\\vec{\\beta})$ as the expected value of the Hamiltonian $H_C$ in the quantum state of equation (19):\n",
"最大割问题(Max-Cut Problem)是图论中常见的一个组合优化问题,在统计物理学和电路设计中都有重要应用。最大割问题是一个 NP 困难问题,因此目前并不存在一个高效的算法能完美地解决该问题。\n",
"\n",
"$$\n",
"F_p(\\vec{\\gamma},\\vec{\\beta}) = \\langle\\vec{\\gamma},\\vec{\\beta}|H_C|\\vec{\\gamma},\\vec{\\beta}\\rangle .\n",
"\\tag{20}\n",
"$$\n",
"在图论中,一个图是由一对集合 $G=(V, E)$ 表示,其中集合 $V$ 中的元素为该图的顶点,集合 $E$ 中的每个元素是一对顶点,表示连接这两个顶点的一条边。例如下方图片中的图可以由 $V=\\{0,1,2,3\\}$ 和 $E=\\{(0,1),(1,2),(2,3),(3,0)\\}$ 表示。\n",
"\n",
"By adjusting the parameters $\\vec{\\gamma},\\vec{\\beta}$, we can get\n",
"![G](figures/maxcut-fig-maxcut_g.png \"图 1:一个有四个顶点和四条边的图\")\n",
"<div style=\"text-align:center\">图 1:一个有四个顶点和四条边的图 </div>\n",
"\n",
"$$\n",
"M_p = \\max_{\\vec{\\gamma},\\vec{\\beta}} F_p(\\vec{\\gamma},\\vec{\\beta})\n",
"\\tag{21}\n",
"$$\n",
"\n",
"as the approximate optimal solution under a given number of layers $p$. So far, we have transformed the problem of searching for the quantum state $|\\psi\\rangle$ into a problem of searching for the parameters $\\vec{\\gamma},\\vec{\\beta}$. It is worth noting that the search space given by $p$ layers of $U_C, U_B$ is larger than that of $p-1$ layers, so\n",
"一个图上的割(cut)是指将该图的顶点集 $V$ 分割成两个互不相交的集合的一种划分,每个割都对应一个边的集合,这些边的两个顶点被划分在不同的集合中。于是我们可以将这个割的大小定义为这个边的集合的大小,即被割开的边的条数。最大割问题就是要找到一个割使得被割开的边的条数最多。图 2 展示了图 1 中图的一个最大割,该最大割的大小为 $4$,即割开了图中所有的边。\n",
"\n",
"$$\n",
"M_p \\geq M_{p-1}.\n",
"\\tag{22}\n",
"$$\n",
"\n",
"In fact, when $p$ is large enough,\n",
"\n",
"$$\n",
"\\lim_{p\\to\\infty} M_p = \\max_z C(z).\n",
"\\tag{23}\n",
"$$\n",
"![Max cut on G](figures/maxcut-fig-maxcut_cut.png \"图 2:图 1 中图的一个最大割\")\n",
"<div style=\"text-align:center\">图 2:图 1 中图的一个最大割 </div>\n",
"\n",
"#### Decoding the quantum solution\n",
"\n",
"In the previous paragraph, we simplify the search for the quantum state $|\\psi\\rangle$ into the search for the parameterized quantum state $|\\vec{\\gamma},\\vec{\\beta}\\rangle$, but at the same time, we have also reduced the search space. That is to say, given the number of layers $p$, there may be no parameters $\\vec{\\gamma},\\vec{\\beta}$ such that $F_p(\\vec{\\gamma},\\vec{\\beta}) = C(z_\\text{opt})$. Suppose that the parameters $\\vec{\\gamma}^*$ and $\\vec{\\beta}^*$ make $F_p$ the largest, that is, $F_p(\\vec{\\gamma}^*,\\vec{\\beta}^* ) = M_p$. Then under ideal circumstances, the quantum state $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ contains the information of an optimal solution. But it should be noted that only $p$ layers are used here, so it is very likely that $M_p < C(z_\\text{opt})$. Therefore, in general $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ only contains information about an approximate optimal solution. Furthermore, we assume that the quantum state $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ is the superposition state of $l$ computational basis state, namely\n",
"假设输入的图 $G=(V, E)$ 有 $n=|V|$ 个顶点和 $m=|E|$ 条边,那么我们可以将最大割问题描述为 $n$ 个比特和 $m$ 个子句的组合优化问题。每个比特对应图 $G$ 中的一个顶点 $v$,其取值 $z_v$ 为 $0$ 或 $1$,分别对应该顶点属于集合 $S_{0}$ 或 $S_{1}$,因此这 $n$ 个比特的每种取值 $z$ 都对应一个割。每个子句则对应图 $G$ 中的一条边 $(u,v)$,一个子句要求其对应的边连接的两个顶点的取值不同,即 $z_u\\neq z_v$,表示该条边被割开。也就是说,当该条边连接这的两个顶点被割划分到不同的集合上时,我们说该子句被满足。因此,对于图 $G$ 中的每条边 $(u,v)$,我们有\n",
"\n",
"$$\n",
"|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle = c_1|z^{(1)}\\rangle + \\cdots + c_l|z^{(l)}\\rangle.\n",
"\\tag{24}\n",
"C_{(u,v)}(z) = z_u+z_v-2z_uz_v,\n",
"\\tag{1}\n",
"$$\n",
"\n",
"Normally, the larger the probability $|c_j|^2$ that a state $|z^{(j)}\\rangle$ is measured on the computational basis, the more likely that the corresponding bit string $z^{(j) }$ is an optimal solution. Thus, we prepare $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ and measure it to get a bit string $z$ and calculate the value of $C(z)$. Repeat this process many times, and we can get a bit string $z$ that makes $C(z)$ close to or even exceed $M_p$.\n",
"\n",
"#### Adiabatic theorem\n",
"\n",
"Why do we use the above method to construct the quantum state $|\\vec{\\gamma},\\vec{\\beta}\\rangle$? QAOA tries to find an approximate optimal solution to an optimization problem. A similar algorithm is the quantum adiabatic algorithm [2] (QAA). The difference is that QAA is designed to find an optimal solution to the optimization problem rather than an approximate one. Similar to QAOA, QAA transforms an optimization problem into a problem of finding the ground state of a Hamiltonian, and uses the adiabatic theorem to solve it. Consider the Hamiltonian\n",
"其中 $C_{(u,v)}(z) = 1$ 当且仅当该条边被割开。否则,该函数等于 $0$。整个组合优化问题的目标函数是\n",
"\n",
"$$\n",
"H(t) = (1-\\frac tT)H_B + \\frac tT H_C,\n",
"\\tag{25}\n",
"C(z) = \\sum_{(u,v)\\in E}C_{(u,v)}(z) = \\sum_{(u,v)\\in E}z_u+z_v-2z_uz_v.\n",
"\\tag{2}\n",
"$$\n",
"\n",
"of a quantum system. At initial, time $t=0$, and the Hamiltonian of the system is $H(0) = H_B$. As time passes, the Hamiltonian of the system gradually changes from $H_B$ to $H_C$. When $t=T$, the Hamiltonian of the system becomes $H(T) = H_C$. The adiabatic theorem in quantum mechanics tells us that if the system is in an eigenstate of $H_B$ at the beginning, then as long as the evolution time $T$ is long enough, the system will be in the eigenstate of the corresponding energy level of $H_C$ when the Hamiltonian of the system completely evolves to $H_C$. Therefore, if the system is initially in $|s\\rangle$, that is, the eigenstate with the largest eigenvalue of $H_B$, after a sufficiently long evolution time $T$, the quantum state of the system will become the eigenstate with the largest eigenvalue of $H_C$. [3]\n",
"\n",
"One way to simulate the evolution of the Hamiltonian $H(t)$ over time $t$ is to alternately apply the unitary transformations $U_C(\\gamma)$ and $U_B(\\beta)$ on the quantum system, and the accuracy of simulation depends on the value of $\\gamma,\\beta$. In addition, in order for the evolution of the system to follow the adiabatic theorem, a sufficiently long evolution time is required, so the value of $p$ is required to be large enough. Therefore, combining equation (22) we can deduce the conclusion in equation (23).\n",
"\n"
"因此,解决最大割问题就是要找到一个取值 $z$ 使得公式(2)中的目标函数最大。"
]
},
{
"cell_type": "markdown",
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-06T07:12:18.621281Z",
"start_time": "2021-01-06T07:12:18.308211Z"
}
},
"metadata": {},
"source": [
"### Example: applying QAOA to solve the Max-Cut Problem\n",
"### 编码最大割问题\n",
"\n",
"The Max-Cut Problem is a common combinatorial optimization problem in graph theory, and it has important applications in statistical physics and circuit design. The maximum cut problem is an NP-complete problem, so there is no efficient algorithm that can solve this problem perfectly.\n",
"\n",
"#### Max-Cut Problem\n",
"\n",
"In graph theory, a graph is represented by a pair of sets $G=(V, E)$, where the elements in the set $V$ are the vertices of the graph, and each element in the set $E$ is a pair of vertices, representing an edge connecting these two vertices. For example, the graph in the figure below is represented by $V=\\{0,1,2,3\\}$ and $E=\\{(0,1),(1,2),(2,3),(3, 0)\\}$.\n",
"\n",
"![G](figures/qaoa-fig-maxcut_g.png \"Figure 1: A graph with four vertices and four edges\")\n",
"<div style=\"text-align:center\">Figure 1: A graph with four vertices and four edges </div>\n",
"\n",
"A cut on a graph refers to a partition of the graph's vertex set $V$ into two disjoint sets. Each cut corresponds to a set of edges, in which the two vertices of each edge are divided into different sets. So we can define the size of this cut as the size of this set of edges, that is, the number of edges being cut. The Max-Cut Problem is to find a cut that maximizes the number of edges being cut. Figure 2 shows a maximum cut of the graph in Figure 1. The size of the maximum cut is $4$, which means that all edges in the graph are cut.\n",
"\n",
"![Max cut on G](figures/qaoa-fig-maxcut_cut.png \"Figure 2: A maximum cut of the graph in Figure 1\")\n",
"<div style=\"text-align:center\">Figure 2: A maximum cut of the graph in Figure 1 </div>\n",
"\n",
"Assuming that the input graph $G=(V, E)$ has $n=|V|$ vertices and $m=|E|$ edges, we can describe the Max-Cut Problem as a combinatorial optimization problem with $n$ bits and $m$ clauses. Each bit corresponds to a vertex $v$ in the graph $G$, and its value $z_v$ is $0$ or $1$, corresponding to the vertex belonging to the set $S_{0}$ or $S_{1}$, respectively. Thus, each value $z$ of these $n$ bits corresponds to a distinct cut. Each clause corresponds to an edge $(u,v)$ in the graph $G$. A clause requires that the two vertices connected by its corresponding edge take different values, namely $z_u\\neq z_v$, which means the edge is cut. In other words, when the two vertices connected by the edge are divided into different sets, we say that the clause is satisfied. Therefore, for each edge $(u,v)$ in the graph $G$, we have\n",
"\n",
"$$\n",
"C_{(u,v)}(z) = z_u+z_v-2z_uz_v,\n",
"\\tag{26}\n",
"$$\n",
"\n",
"where $C_{(u,v)}(z) = 1$ if and only if the edge is cut. Otherwise, the function is equal to $0$. The objective function of the entire combinatorial optimization problem is\n",
"\n",
"$$\n",
"C(z) = \\sum_{(u,v)\\in E}C_{(u,v)}(z) = \\sum_{(u,v)\\in E}z_u+z_v-2z_uz_v.\n",
"\\tag{27}\n",
"$$\n",
"\n",
"Therefore, to solve the maximum cut problem is to find a value $z$ that maximizes the objective function in equation (27).\n",
"\n",
"#### Encoding Max-Cut Problem\n",
"\n",
"Here we take the Max-Cut Problem as an example to further elaborate on QAOA. In order to transform the Max-Cut Problem into a quantum problem, we need to use $n$ qubits, where each qubit corresponds to a vertex in the graph $G$. A qubit being in a quantum state $|0\\rangle$ or $|1\\rangle$ indicates that its corresponding vertex belongs to the set $S_{0}$ or $S_{1}$, respectively. It is worth noting that $|0\\rangle$ and $|1\\rangle$ are the two eigenstates of Pauli $Z$ gate, and their eigenvalues ​​are respectively $1$ and $-1$, namely\n",
"为了将最大割问题转化为一个量子问题,我们要用到 $n$ 个量子比特,每个量子比特对应图 $G$ 中的一个顶点。一个量子比特处于量子态 $|0\\rangle$ 或 $|1\\rangle$,表示其对应的顶点属于集合 $S_{0}$ 或 $S_{1}$。值得注意的是,$|0\\rangle$ 和 $|1\\rangle$ 是 Pauli $Z$ 门的两个本征态,并且它们的本征值分别为 $1$ 和 $-1$,即\n",
"\n",
"$$\n",
"\\begin{align}\n",
"Z|0\\rangle&=|0\\rangle,\\tag{28}\\\\\n",
"Z|1\\rangle&=-|1\\rangle.\\tag{29}\n",
"Z|0\\rangle&=|0\\rangle,\\tag{3}\\\\\n",
"Z|1\\rangle&=-|1\\rangle.\\tag{4}\n",
"\\end{align}\n",
"$$\n",
"\n",
"Therefore, we can use Pauli $Z$ gate to construct the Hamiltonian $H_C$ of the Max-Cut Problem. Because mapping $f(x):x\\to(x+1)/2$ maps $-1$ to $0$ and $1$ to $1$, we can replace $z$ in equation (27) with $(Z+I)/2$ ($I$ is the identity matrix) to get the Hamiltonian corresponding to the objective function of the original problem:\n",
"因此我们可以使用 Pauli $Z$ 门来构建该最大割问题的哈密顿量 $H_C$。因为通过映射 $f(x):x\\to(x+1)/2$ 可以将 $-1$ 映射到 $0$ 上 并且仍将 $1$ 映射到 $1$ 上,所以我们可以将式(2)中的 $z$ 替换为 $(Z+I)/2$($I$ 是单位矩阵),得到原问题目标函数对应的哈密顿量\n",
"\n",
"$$\n",
"\\begin{align}\n",
"H_C &= \\sum_{(u,v)\\in E} \\frac{Z_u+I}{2} + \\frac{Z_v+I}{2}-2\\cdot\\frac{Z_u+I}{2} \\frac{Z_v+I}{2}\\tag{30}\\\\\n",
"&= \\sum_{(u,v)\\in E} \\frac{Z_u+Z_v+2I-(Z_uZ_v+Z_u+Z_v+I)}{2}\\tag{31}\\\\\n",
"&= \\sum_{(u,v)\\in E} \\frac{I-Z_uZ_v}{2}.\\tag{32}\n",
"H_C &= \\sum_{(u,v)\\in E} \\frac{Z_u+I}{2} + \\frac{Z_v+I}{2} - 2\\cdot\\frac{Z_u+I}{2}\\frac{Z_v+I}{2}\\tag{5}\\\\\n",
"&= \\sum_{(u,v)\\in E} \\frac{Z_u+Z_v+2I - (Z_uZ_v+Z_u+Z_v+I)}{2}\\tag{6}\\\\\n",
"&= \\sum_{(u,v)\\in E} \\frac{I - Z_uZ_v}{2}.\\tag{7}\n",
"\\end{align}\n",
"$$\n",
"\n",
"The expected value of this Hamiltonian for a quantum state $|\\psi\\rangle$ is\n",
"该哈密顿量关于一个量子态 $|\\psi\\rangle$ 的期望值为\n",
"\n",
"$$\n",
"\\begin{align}\n",
"\\langle\\psi|H_C|\\psi\\rangle &= \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{I-Z_uZ_v}{2}|\\psi\\rangle\\tag{33} \\\\\n",
"&= \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{I}{2}|\\psi\\rangle-\\langle\\psi|\\sum_{(u,v)\\in E} \\frac{Z_uZ_v}{2}|\\psi\\rangle\\tag{34}\\\\\n",
"&= \\frac{|E|}{2}-\\frac{1}{2}\\langle\\psi|\\sum_{(u,v)\\in E} Z_uZ_v|\\psi\\rangle.\\tag{35}\n",
"\\langle\\psi|H_C|\\psi\\rangle &= \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{I - Z_uZ_v}{2}|\\psi\\rangle\\tag{8}\\\\\n",
"&= \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{I}{2}|\\psi\\rangle - \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{Z_uZ_v}{2}|\\psi\\rangle\\tag{9}\\\\\n",
"&= \\frac{|E|}{2} - \\frac{1}{2}\\langle\\psi|\\sum_{(u,v)\\in E} Z_uZ_v|\\psi\\rangle.\\tag{10}\n",
"\\end{align}\n",
"$$\n",
"\n",
"If we define\n",
"如果我们记\n",
"\n",
"$$\n",
"H_D = -\\sum_{(u,v)\\in E} Z_uZ_v,\n",
"\\tag{36}\n",
"\\tag{11}\n",
"$$\n",
"\n",
"then finding the quantum state $|\\psi\\rangle$ that maximizes $\\langle\\psi|H_C|\\psi\\rangle$ is equivalent to finding the quantum state $|\\psi\\rangle$ such that $\\langle\\psi|H_D|\\psi \\rangle$ is the largest."
"那么找到量子态 $|\\psi\\rangle$ 使得 $\\langle\\psi|H_C|\\psi\\rangle$ 最大等价于找到量子态 $|\\psi\\rangle$ 使得 $\\langle\\psi|H_D|\\psi\\rangle$ 最大。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Paddle Quantum Implementation\n",
"## Paddle Quantum 实现\n",
"\n",
"Let's take the Max-Cut Problem as an example and use the QAOA algorithm to solve it with Paddle Quantum. There are many ways to find the parameters $\\vec{\\gamma},\\vec{\\beta}$. Here we use the gradient descent method in classical machine learning.\n",
"接下来,我们用量桨实现 QAOA 来求解最大割问题。有许多方法可以找到参数 $\\vec{\\gamma},\\vec{\\beta}$,我们这里使用经典机器学习中的梯度下降方法。\n",
"\n",
"To implement QAOA on Paddle Quantum, the first thing to do is to import the required packages. Among them, the `networkx` package can help us handle graphs conveniently.\n",
"\n"
"要在量桨上实现 QAOA,首先要做的便是加载需要用到的包。其中 `networkx` 包可以帮助我们方便地处理图。"
]
},
{
......@@ -357,20 +111,47 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:10:24.136791Z",
"start_time": "2021-03-09T06:10:19.007907Z"
"end_time": "2021-04-30T09:11:04.006915Z",
"start_time": "2021-04-30T09:11:03.951557Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"<style>pre { white-space: pre !important; }</style>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.core.display import HTML\n",
"display(HTML(\"<style>pre { white-space: pre !important; }</style>\"))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-30T09:11:08.078417Z",
"start_time": "2021-04-30T09:11:04.569758Z"
}
},
"outputs": [],
"source": [
"# Import related modules from Paddle Quantum and PaddlePaddle\n",
"# 加载量桨、飞桨的相关模块\n",
"import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import pauli_str_to_matrix\n",
"\n",
"# Import additional packages needed\n",
"# 加载额外需要用到的包\n",
"import numpy as np\n",
"from numpy import pi as PI\n",
"import matplotlib.pyplot as plt\n",
"import networkx as nx"
]
......@@ -379,16 +160,16 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we generate the graph $G$ in the Max-Cut Problem. For the convenience of computation, the vertices here are labeled starting from $0$."
"接下来,我们生成该最大割问题中的图 $G$。为了运算方便,这里的顶点从 $0$ 开始计数。"
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:10:24.538191Z",
"start_time": "2021-03-09T06:10:24.142186Z"
"end_time": "2021-04-30T09:11:08.411878Z",
"start_time": "2021-04-30T09:11:08.093215Z"
}
},
"outputs": [
......@@ -404,7 +185,7 @@
}
],
"source": [
"# n is the number of vertices in the graph G, which is also the number of qubits\n",
"# n 是图 G 的顶点数,同时也是量子比特的个数\n",
"n = 4\n",
"G = nx.Graph()\n",
"V = range(n)\n",
......@@ -412,7 +193,7 @@
"E = [(0, 1), (1, 2), (2, 3), (3, 0)]\n",
"G.add_edges_from(E)\n",
"\n",
"# Print out the generated graph G\n",
"# 将生成的图 G 打印出来\n",
"pos = nx.circular_layout(G)\n",
"options = {\n",
" \"with_labels\": True,\n",
......@@ -433,18 +214,18 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Encoding Hamiltonian\n",
"### 编码哈密顿量\n",
"\n",
"In Paddle Quantum, a Hamiltonian can be input in the form of `list`. Here we construct the Hamiltonian $H_D$ in equation (36)."
"量桨中,哈密顿量可以以 `list` 的形式输入。这里我们构建式(11)中的哈密顿量 $H_D$。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:10:24.568875Z",
"start_time": "2021-03-09T06:10:24.555025Z"
"end_time": "2021-04-30T09:11:08.426170Z",
"start_time": "2021-04-30T09:11:08.418352Z"
}
},
"outputs": [
......@@ -457,10 +238,10 @@
}
],
"source": [
"# Construct the Hamiltonian H_D in the form of list\n",
"# 以 list 的形式构建哈密顿量 H_D\n",
"H_D_list = []\n",
"for (u, v) in E:\n",
" H_D_list.append([-1.0,'z'+str(u) +',z' + str(v)])\n",
" H_D_list.append([-1.0, 'z'+str(u) + ',z' + str(v)])\n",
"print(H_D_list)"
]
},
......@@ -468,23 +249,23 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"As you can see, in this example, the Hamiltonian $H_D$ is\n",
"可以看到,在这个例子中,哈密顿量 $H_D$ 为\n",
"\n",
"$$\n",
"H_D = -Z_0Z_1-Z_1Z_2-Z_2Z_3-Z_3Z_0.\n",
"\\tag{37}\n",
"H_D = -Z_0Z_1 - Z_1Z_2 - Z_2Z_3 - Z_3Z_0.\n",
"\\tag{12}\n",
"$$\n",
"\n",
"We can view the matrix form of the Hamiltonian $H_D$ and get information of its eigenvalues:"
"我们可以查看哈密顿量 $H_D$ 的矩阵形式,并且获取它的本征值信息:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:10:24.589057Z",
"start_time": "2021-03-09T06:10:24.578446Z"
"end_time": "2021-04-30T09:11:08.792299Z",
"start_time": "2021-04-30T09:11:08.777145Z"
}
},
"outputs": [
......@@ -498,11 +279,11 @@
}
],
"source": [
"# Convert Hamiltonian H_D from list form to matrix form\n",
"# 将哈密顿量 H_D 从 list 形式转为矩阵形式\n",
"H_D_matrix = pauli_str_to_matrix(H_D_list, n)\n",
"# Take out the elements on the diagonal of H_D\n",
"# 取出 H_D 对角线上的元素\n",
"H_D_diag = np.diag(H_D_matrix).real\n",
"# Get the maximum eigenvalue of H_D\n",
"# 获取 H_D 的最大本征值\n",
"H_max = np.max(H_D_diag)\n",
"\n",
"print(H_D_diag)\n",
......@@ -513,54 +294,54 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Building the QAOA circuit\n",
"### 搭建 QAOA 电路\n",
"\n",
"Earlier we introduced that QAOA needs to apply two unitary transformations $U_C(\\gamma)$ and $U_B(\\beta)$ alternately on the initial state $|s\\rangle = |+\\rangle^{\\otimes n}$. Here, we use the quantum gates and quantum circuit templates provided in Paddle Quantum to build a quantum circuit to achieve this step. It should be noted that in the Max-Cut Problem, we simplify the problem of maximizing the expected value of the Hamiltonian $H_C$ to the problem of maximizing the expected value of the Hamiltonian $H_D$, so the unitary transformations to be used are $U_D(\\gamma)$ and $U_B(\\beta)$. By alternately placing two circuit modules with adjustable parameters, we are able to build a QAOA circuit\n",
"前面我们介绍了 QAOA 需要将两个酉变换 $U_C(\\gamma)$ 和 $U_B(\\beta)$ 交替地作用在初始态 $|s\\rangle = |+\\rangle^{\\otimes n}$ 上。在这里,我们使用量桨中提供的量子门和量子电路模板搭建出一个量子电路来实现这一步骤。要注意的是,在最大割问题中,我们将最大化哈密顿量 $H_C$ 的期望值的问题简化为了最大化哈密顿量 $H_D$ 的期望值的问题,因此要用到的酉变换也就变成了 $U_D(\\gamma)$ 和 $U_B(\\beta)$。通过交替地摆放两个参数可调的电路模块,我们得以搭建QAOA电路\n",
"\n",
"$$\n",
"U_B(\\beta_p)U_D(\\gamma_p)\\cdots U_B(\\beta_1)U_D(\\gamma_1),\n",
"\\tag{38}\n",
"\\tag{13}\n",
"$$\n",
"\n",
"where $U_D(\\gamma) = e^{-i\\gamma H_D}$ can be constructed with the circuit in the figure below. Another unitary transformation $U_B(\\beta)$ is equivalent to applying a $R_x$ gate to each qubit.\n",
"其中,$U_D(\\gamma) = e^{-i\\gamma H_D}$ 可以由下图中的电路搭建实现。另一个酉变换 $U_B(\\beta)$ 则等价于在每个量子比特上作用一个 $R_x$ 门。\n",
"\n",
"![U_D circuit](figures/maxcut-fig-cir_ud.png \"图 3:酉变换 $e^{i\\gamma Z\\otimes Z}$ 的量子电路实现\")\n",
"<div style=\"text-align:center\">图 3:酉变换 $e^{i\\gamma Z\\otimes Z}$ 的量子电路实现 </div>\n",
"\n",
"![U_D circuit](figures/qaoa-fig-cir_ud.png \"Figure 3: Quantum circuit of unitary transformation $e^{i\\gamma Z\\otimes Z}$\")\n",
"<div style=\"text-align:center\">Figure 3: Quantum circuit of unitary transformation $e^{i\\gamma Z\\otimes Z}$</div>\n",
"\n",
"Therefore, the quantum circuit that realizes a layer of unitary transformation $U_B(\\beta)U_D(\\gamma)$ is shown in Figure 4.\n",
"因此,实现一层酉变换 $U_B(\\beta)U_D(\\gamma)$ 的量子电路如图 4 所示。\n",
"\n",
"![U_BU_D circuit](figures/qaoa-fig-cir_ubud.png \"Figure 4: Quantum circuit of unitary transformation $U_B(\\beta)U_D(\\gamma)$\")\n",
"<div style=\"text-align:center\">Figure 4: Quantum circuit of unitary transformation $U_B(\\beta)U_D(\\gamma)$ </div>\n",
"![U_BU_D circuit](figures/maxcut-fig-cir_ubud.png \"图 4:酉变换 $U_B(\\beta)U_D(\\gamma)$ 的量子电路实现\")\n",
"<div style=\"text-align:center\">图 4:酉变换 $U_B(\\beta)U_D(\\gamma)$ 的量子电路实现 </div>\n",
"\n",
"In Paddle Quantum, the default initial state of each qubit is $|0\\rangle$ (the initial state can be customized by input parameters). We can add a layer of Hadamard gates to change the state of each qubit from $|0\\rangle$ to $|+\\rangle$ so that we get the initial state $|s\\rangle = |+\\rangle^{\\otimes n}$ required by QAOA. In Paddle Quantum, we can add a layer of Hadamard gates to the quantum circuit by calling `superposition_layer()`.\n",
"\n"
"量桨中,电路运行前每个量子比特默认的初始状态为 $|0\\rangle$(可以通过输入参数来自定义初始状态),我们可以通过添加一层 Hadamard 门使每个量子比特的状态由 $|0\\rangle$ 变为 $|+\\rangle$,由此得到 QAOA 要求的初始态 $|s\\rangle = |+\\rangle^{\\otimes n}$。在量桨中,可以通过调用 `superposition_layer()` 在量子电路中添加一层 Hadamard 门。"
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:10:24.716543Z",
"start_time": "2021-03-09T06:10:24.700063Z"
"end_time": "2021-04-30T09:11:10.245237Z",
"start_time": "2021-04-30T09:11:10.238838Z"
}
},
"outputs": [],
"source": [
"def circuit_QAOA(p, gamma, beta):\n",
" # Initialize the quantum circuit of n qubits\n",
" # 初始化 n 个量子比特的量子电路\n",
" cir = UAnsatz(n)\n",
" # Prepare quantum state |s>\n",
" # 制备量子态 |s>\n",
" cir.superposition_layer()\n",
" # Build a circuit with p layers\n",
" # 搭建 p 层电路\n",
" for layer in range(p):\n",
" # Build the circuit of U_D\n",
" # 搭建 U_D 的电路\n",
" for (u, v) in E:\n",
" cir.cnot([u, v])\n",
" cir.rz(gamma[layer], v)\n",
" cir.cnot([u, v])\n",
"\n",
" # Build the circuit of U_B, that is, add a layer of R_x gates\n",
" # 搭建 U_B 的电路,即添加一层 R_x 门\n",
" for v in V:\n",
" cir.rx(beta[layer], v)\n",
"\n",
......@@ -571,59 +352,58 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"After running the constructed QAOA quantum circuit, we obtain the output state\n",
"搭建 QAOA 量子电路的工作完成后,如果运行该量子电路,得到的输出态为\n",
"\n",
"$$\n",
"|\\vec{\\gamma},\\vec{\\beta}\\rangle = U_B(\\beta_p)U_D(\\gamma_p)\\cdots U_B(\\beta_1)U_D(\\gamma_1)|s\\rangle.\n",
"\\tag{39}\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Calculating the loss function\n",
"\\tag{14}\n",
"$$\n",
"\n",
"### 计算损失函数\n",
"\n",
"From the output state of the circuit built in the previous step, we can calculate the objective function of the maximum cut problem\n",
"由上一步搭建的电路的输出态,我们可以计算最大割问题的目标函数\n",
"\n",
"$$\n",
"F_p(\\vec{\\gamma},\\vec{\\beta}) = \\langle\\vec{\\gamma},\\vec{\\beta}|H_D|\\vec{\\gamma},\\vec{\\beta}\\rangle.\n",
"\\tag{40}\n",
"\\tag{15}\n",
"$$\n",
"\n",
"To maximize the objective function is equivalent to minimizing $-F_p$. Therefore, we define $L(\\vec{\\gamma},\\vec{\\beta}) = -F_p(\\vec{\\gamma},\\vec{\\beta})$ as the loss function, that is, the function to be minimized. Then, we use a classical optimization algorithm to find the optimal parameters $\\vec{\\gamma},\\vec{\\beta}$. The following code shows a complete QAOA network built with Paddle Quantum and PaddlePaddle:"
"要最大化该目标函数等价于最小化 $-F_p$。因此我们定义 $L(\\vec{\\gamma},\\vec{\\beta}) = -F_p(\\vec{\\gamma},\\vec{\\beta})$ 为损失函数,即要最小化的函数,然后利用经典的优化算法寻找最优参数 $\\vec{\\gamma},\\vec{\\beta}$。下面的代码给出了通过量桨和飞桨搭建的完整 QAOA 网络:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:10:26.069461Z",
"start_time": "2021-03-09T06:10:26.057685Z"
"end_time": "2021-04-30T09:11:11.218109Z",
"start_time": "2021-04-30T09:11:11.206471Z"
}
},
"outputs": [],
"source": [
"class Net(paddle.nn.Layer):\n",
" def __init__(self, p, dtype=\"float64\",):\n",
" def __init__(\n",
" self,\n",
" p,\n",
" dtype=\"float64\",\n",
" ):\n",
" super(Net, self).__init__()\n",
"\n",
" self.p = p\n",
" self.gamma = self.create_parameter(shape=[self.p], \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI), \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 * PI), \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*np.pi),\n",
" dtype=dtype, is_bias=False)\n",
"\n",
" def forward(self):\n",
" # Define QAOA's quantum circuit\n",
" # 定义 QAOA 的量子电路\n",
" cir = circuit_QAOA(self.p, self.gamma, self.beta)\n",
" # Run the quantum circuit\n",
" # 运行该量子电路\n",
" cir.run_state_vector()\n",
" # Calculate the loss function\n",
" # 计算损失函数\n",
" loss = -cir.expecval(H_D_list)\n",
"\n",
" return loss, cir"
......@@ -633,42 +413,41 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Training quantum neural network\n",
"\n",
"After defining the quantum neural network for QAOA, we use the gradient descent method to update the parameters in the network to maximize the expected value in equation (40)."
"### 训练量子神经网络\n",
"定义好了用于 QAOA 的量子神经网络后,我们使用梯度下降的方法来更新其中的参数,使得式(15)的期望值最大。"
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:10:26.971045Z",
"start_time": "2021-03-09T06:10:26.961776Z"
"end_time": "2021-04-30T09:11:12.968989Z",
"start_time": "2021-04-30T09:11:12.961264Z"
}
},
"outputs": [],
"source": [
"p = 4 # Number of layers in the quantum circuit\n",
"ITR = 120 # Number of training iterations\n",
"LR = 0.1 # Learning rate of the optimization method based on gradient descent\n",
"SEED = 1024 # Set global RNG seed "
"p = 4 # 量子电路的层数\n",
"ITR = 120 # 训练迭代的次数\n",
"LR = 0.1 # 基于梯度下降的优化方法的学习率\n",
"SEED = 1024 #设置全局随机数种子"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here, we optimize the network defined above in PaddlePaddle."
"这里,我们在飞桨中优化上面定义的网络。"
]
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:11:07.397318Z",
"start_time": "2021-03-09T06:10:27.928944Z"
"end_time": "2021-04-30T09:11:54.550338Z",
"start_time": "2021-04-30T09:11:21.244581Z"
}
},
"outputs": [
......@@ -676,21 +455,31 @@
"name": "stdout",
"output_type": "stream",
"text": [
"iter: 10 loss: -3.8886\n",
"iter: 20 loss: -3.9134\n",
"iter: 30 loss: -3.9659\n",
"iter: 40 loss: -3.9906\n",
"iter: 50 loss: -3.9979\n",
"iter: 60 loss: -3.9993\n",
"iter: 70 loss: -3.9998\n",
"iter: 80 loss: -3.9999\n",
"iter: 90 loss: -4.0000\n",
"iter: 100 loss: -4.0000\n",
"iter: 110 loss: -4.0000\n",
"iter: 120 loss: -4.0000\n",
"Optimized parameters gamma:\n",
"iter: 10 loss: -3.8886\n",
"iter: 20 loss: -3.9134\n",
"iter: 30 loss: -3.9659\n",
"iter: 40 loss: -3.9906\n",
"iter: 50 loss: -3.9979\n",
"iter: 60 loss: -3.9993\n",
"iter: 70 loss: -3.9998\n",
"iter: 80 loss: -3.9999\n",
"iter: 90 loss: -4.0000\n",
"iter: 100 loss: -4.0000\n",
"iter: 110 loss: -4.0000\n",
"iter: 120 loss: -4.0000\n",
"\n",
"训练后的电路:\n",
"--H----*-----------------*--------------------------------------------------X----Rz(3.140)----X----Rx(0.824)----*-----------------*--------------------------------------------------X----Rz(0.737)----X----Rx(2.506)----*-----------------*--------------------------------------------------X----Rz(4.999)----X----Rx(4.854)----*-----------------*--------------------------------------------------X----Rz(0.465)----X----Rx(1.900)--\n",
" | | | | | | | | | | | | | | | | \n",
"--H----X----Rz(3.140)----X----*-----------------*---------------------------|-----------------|----Rx(0.824)----X----Rz(0.737)----X----*-----------------*---------------------------|-----------------|----Rx(2.506)----X----Rz(4.999)----X----*-----------------*---------------------------|-----------------|----Rx(4.854)----X----Rz(0.465)----X----*-----------------*---------------------------|-----------------|----Rx(1.900)--\n",
" | | | | | | | | | | | | | | | | \n",
"--H---------------------------X----Rz(3.140)----X----*-----------------*----|-----------------|----Rx(0.824)---------------------------X----Rz(0.737)----X----*-----------------*----|-----------------|----Rx(2.506)---------------------------X----Rz(4.999)----X----*-----------------*----|-----------------|----Rx(4.854)---------------------------X----Rz(0.465)----X----*-----------------*----|-----------------|----Rx(1.900)--\n",
" | | | | | | | | | | | | | | | | \n",
"--H--------------------------------------------------X----Rz(3.140)----X----*-----------------*----Rx(0.824)--------------------------------------------------X----Rz(0.737)----X----*-----------------*----Rx(2.506)--------------------------------------------------X----Rz(4.999)----X----*-----------------*----Rx(4.854)--------------------------------------------------X----Rz(0.465)----X----*-----------------*----Rx(1.900)--\n",
" \n",
"优化后的参数 gamma:\n",
" [3.14046713 0.73681226 4.99897226 0.46481489]\n",
"Optimized parameters beta:\n",
"优化后的参数 beta:\n",
" [0.82379898 2.50618308 4.85422542 1.90024859]\n"
]
}
......@@ -699,56 +488,58 @@
"paddle.seed(SEED)\n",
"\n",
"net = Net(p)\n",
"# Use Adam optimizer\n",
"# 使用 Adam 优化器\n",
"opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"# Gradient descent iteration\n",
"# 梯度下降循环\n",
"for itr in range(1, ITR + 1):\n",
" # Run the network defined above\n",
" # 运行上面定义的网络\n",
" loss, cir = net()\n",
" # Calculate the gradient and optimize\n",
" # 计算梯度并优化\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" opt.clear_grad()\n",
" if itr% 10 == 0:\n",
" print(\"iter:\", itr, \"loss:\", \"%.4f\"% loss.numpy())\n",
" if itr % 10 == 0:\n",
" print(\"iter:\", itr, \" loss:\", \"%.4f\" % loss.numpy())\n",
" if itr % ITR == 0:\n",
" print(\"\\n训练后的电路:\")\n",
" print(cir)\n",
"\n",
"gamma_opt = net.gamma.numpy()\n",
"print(\"Optimized parameters gamma:\\n\", gamma_opt)\n",
"print(\"优化后的参数 gamma:\\n\", gamma_opt)\n",
"beta_opt = net.beta.numpy()\n",
"print(\"Optimized parameters beta:\\n\", beta_opt)"
"print(\"优化后的参数 beta:\\n\", beta_opt)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Decoding the quantum solution\n",
"\n",
"After obtaining the minimum value of the loss function and the corresponding set of parameters $\\vec{\\gamma}^*,\\vec{\\beta}^*$, our task has not been completed. In order to obtain an approximate solution to the Max-Cut Problem, it is necessary to decode the solution to the classical optimization problem from the quantum state $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ output by QAOA. Physically, to decode a quantum state, we need to measure it and then calculate the probability distribution of the measurement results:\n",
"### 解码量子答案\n",
"当求得损失函数的最小值以及相对应的一组参数 $\\vec{\\gamma}^*,\\vec{\\beta}^*$ 后,我们的任务还没有完成。为了进一步求得 Max-Cut 问题的近似解,需要从 QAOA 输出的量子态 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 中解码出经典优化问题的答案。物理上,解码量子态需要对量子态进行测量,然后统计测量结果的概率分布:\n",
"\n",
"$$\n",
"p(z)=|\\langle z|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle|^2.\n",
"\\tag{41}\n",
"\\tag{16}\n",
"$$\n",
"\n",
"Usually, the greater the probability of a certain bit string, the greater the probability that it corresponds to an optimal solution of the Max-Cut problem.\n",
"通常情况下,某个比特串出现的概率越大,意味着其对应 Max-Cut 问题最优解的可能性越大。\n",
"\n",
"Paddle Quantum provides a function to view the probability distribution of the measurement results of the state output by the QAOA quantum circuit:"
"Paddle Quantum 提供了查看 QAOA 量子电路输出状态的测量结果概率分布的函数:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 10,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:11:08.010481Z",
"start_time": "2021-03-09T06:11:07.444837Z"
"end_time": "2021-04-30T09:11:55.548009Z",
"start_time": "2021-04-30T09:11:54.556907Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEWCAYAAABrDZDcAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Z1A+gAAAACXBIWXMAAAsTAAALEwEAmpwYAAAbM0lEQVR4nO3de9hcZX3u8e+dcBRQQRAtCYbWUMUDqAHZtdsDgg1bDVBROSkqNraSCpe2CluLgnZv1MqubAI1ioh2S/BsqhGwKnZrt5iAKASMpAgSFI0iB2UDRu7+sVZgmMw775r3XWtm8q77c11zZdbpt34TwvxmPetZzyPbREREe80adQIRETFaKQQRES2XQhAR0XIpBBERLZdCEBHRcikEEREtt9WoExjUrrvu6nnz5o06jYiILcqVV175S9u79dq2xRWCefPmsXr16lGnERGxRZF080Tb0jQUEdFyKQQRES2XQhAR0XIpBBERLZdCEBHRcikEEREtl0IQEdFyKQQRES23xT1QFlu2ead8ecrH3nTmi2vMJCI2yRVBRETLpRBERLRco4VA0kJJayWtk3RKj+2vkbRB0tXl6/VN5hMREZtr7B6BpNnAUuAQYD2wStIK29d17Xqx7SVN5REREf01eUVwALDO9o227weWA4c1eL6IiJiCJgvBHsAtHcvry3XdXibpB5I+I2lur0CSFktaLWn1hg0bmsg1IqK1Rn2z+F+AebafDnwVuLDXTraX2V5ge8Fuu/WcVyEiIqaoyUJwK9D5C39Oue5Btn9l+75y8SPAsxrMJyIiemiyEKwC5kvaS9I2wFHAis4dJD2+Y3ERcH2D+URERA+N9RqyvVHSEuBSYDbwUdtrJJ0BrLa9AniTpEXARuB24DVN5RMREb01OsSE7ZXAyq51p3W8PxU4tckcIiKiv1HfLI6IiBHLoHMRLZJB/6KXXBFERLRcCkFERMulEEREtFwKQUREy6UQRES0XApBRETLpRBERLRcCkFERMulEEREtFwKQUREy6UQRES0XApBRETLpRBERLRcCkFERMulEEREtFwKQUREy6UQRES0XApBRETLpRBERLRcCkFERMulEEREtFwKQUREy6UQRES0XApBRETLpRBERLRcCkFERMulEEREtFwKQUREy6UQRES03KSFQNJzJO1Qvj9O0lmSnlAluKSFktZKWifplD77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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -760,7 +551,7 @@
}
],
"source": [
"# Repeat the simulated measurement of the circuit output state 1024 times\n",
"# 模拟重复测量电路输出态 1024 次\n",
"prob_measure = cir.measure(plot=True)"
]
},
......@@ -768,21 +559,21 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"After measurement, we can find the bit string with the highest probability of occurrence. Let the vertices whose bit values are $0$ in the bit string belong to the set $S_0$ and the vertices whose bit values are $1$ belong to the set $S_1$. The set of edges between these two vertex sets is a possible maximum cut of the graph.\n",
"通过测量,找到出现几率最高的比特串。 此时,记其在该比特串中对应的比特取值为 $0$ 的顶点属于集合 $S_0$ 以及对应比特取值为 $1$ 的顶点属于集合 $S_1$,这两个顶点集合之间存在的边就是该图的一个可能的最大割方案。\n",
"\n",
"The following code selects the bit string with the greatest chance of appearing in the measurement result, then maps it back to the classic solution, and draws the corresponding maximum cut:\n",
"- The red vertex belongs to the set $S_0$,\n",
"- The blue vertex belongs to the set $S_1$,\n",
"- The dashed line indicates the edge being cut."
"下面的代码选取测量结果中出现几率最大的比特串,然后将其映射回经典解,并且画出对应的最大割方案:\n",
"- 红色顶点属于集合 $S_0$,\n",
"- 蓝色顶点属于集合 $S_1$,\n",
"- 虚线表示被割的边。"
]
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 11,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T06:11:08.356970Z",
"start_time": "2021-03-09T06:11:08.052122Z"
"end_time": "2021-04-30T09:11:55.906817Z",
"start_time": "2021-04-30T09:11:55.625551Z"
}
},
"outputs": [
......@@ -790,7 +581,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"The bit string form of the cut found: 0101\n"
"找到的割的比特串形式: 0101\n"
]
},
{
......@@ -805,11 +596,11 @@
}
],
"source": [
"# Find the most frequent bit string in the measurement results\n",
"# 找到测量结果中出现几率最大的比特串\n",
"cut_bitstring = max(prob_measure, key=prob_measure.get)\n",
"print(\"The bit string form of the cut found:\", cut_bitstring)\n",
"print(\"找到的割的比特串形式:\", cut_bitstring)\n",
"\n",
"# Draw the cut corresponding to the bit string obtained above on the graph\n",
"# 在图上画出上面得到的比特串对应的割\n",
"node_cut = [\"blue\" if cut_bitstring[v] == \"1\" else \"red\" for v in V]\n",
"\n",
"edge_cut = [\n",
......@@ -833,7 +624,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"As you can see, in this example, QAOA has found a maximum cut on the graph.\n"
"可以看到,在这个例子中 QAOA 找到了图上的一个最大割。"
]
},
{
......@@ -842,13 +633,9 @@
"source": [
"_______\n",
"\n",
"## References\n",
"## 参考文献\n",
"\n",
"[1] Farhi, E., Goldstone, J. & Gutmann, S. A Quantum Approximate Optimization Algorithm. [arXiv:1411.4028 (2014).](https://arxiv.org/abs/1411.4028)\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",
"\n",
"[3] Duan, R. Quantum Adiabatic Theorem Revisited. [arXiv:2003.03063 (2020).](https://arxiv.org/abs/2003.03063)"
"[1] Farhi, E., Goldstone, J. & Gutmann, S. A Quantum Approximate Optimization Algorithm. [arXiv:1411.4028 (2014).](https://arxiv.org/abs/1411.4028)"
]
}
],
......@@ -879,14 +666,9 @@
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {
"height": "calc(100% - 180px)",
"left": "10px",
"top": "150px",
"width": "426.667px"
},
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
"toc_window_display": false
},
"varInspector": {
"cols": {
......
......@@ -2,368 +2,111 @@
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-06T07:10:17.389768Z",
"start_time": "2021-01-06T07:10:17.379639Z"
}
},
"source": [
"# 量子近似优化算法\n",
"# Solving Max-Cut Problem with QAOA\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 概览\n",
"\n",
"量子近似优化算法(Quantum Approximate Optimization Algorithm, QAOA)是可以在近期的有噪中等规模量子(Noisy Intermediate-Scale Quantum, NISQ)设备上运行且具有广泛应用前景的量子算法。QAOA 由 Edward Farhi 等人于 2014 年提出[1],其目的是近似地求解组合优化问题(combinatorial optimization problems)。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 组合优化问题\n",
"\n",
"在应用数学和理论计算机科学的领域中,组合优化是在一个有限的对象集中找出最优对象的一类课题。简单来说,组合优化问题是指问题的所有解是由离散变量组成的,然后在离散的解集中寻找最优解。组合优化问题涉及的范围很广,且常见于实际生活中,例如飞机航线的设计、快递物流路线的规划等。\n",
"\n",
"具体来说,一个组合优化问题可以由 $n$ 个比特(bit)和 $m$ 个子句(clause)描述。每个比特的取值为 $0$ 或 $1$,我们用 $z_j$ 表示第 $j$ 个比特的取值。因此,这 $n$ 个比特的取值可以由比特串 $z=z_1z_2\\dots z_n$ 表示。每个子句都是对部分比特的一个限制条件,例如一个子句可以要求第 $2$ 个比特的取值为 $0$,或者可以要求第 $3$ 个比特和第 $5$ 个比特的取值相同,等等。对于第 $j$ 个子句,我们定义一个与之相关的函数\n",
"\n",
"$$\n",
"C_j(z)=\n",
"\\begin{cases}\n",
"1 & \\text{如果 $n$ 个比特的取值 $z$ 满足子句 $j$ 表明的条件}\\\\\n",
"0 & \\text{如果 $n$ 个比特的取值 $z$ 不满足子句 $j$ 表明的条件}\n",
"\\end{cases}.\n",
"\\tag{1}\n",
"$$\n",
"\n",
"例如,如果第一个子句要求第二个比特的取值为 0,那么我们有 $C_1(z_10z_3\\dots z_n)=1$ 和 $C_1(z_11z_3\\dots z_n)=0$。\n",
"\n",
"由公式(1)中我们对于每个子句定义的函数 $C_j$,我们可以定义该组合优化问题的目标函数(objective function)\n",
"\n",
"$$\n",
"C(z)=\\sum_{j=1}^m w_jC_j(z),\n",
"\\tag{2}\n",
"$$\n",
"\n",
"其中 $w_j$ 是第 $j$ 个子句的权重(weight)。组合优化问题就是要找到一个取值 $z$ 使得目标函数 $C(z)$ 的值最大,即\n",
"\n",
"$$\n",
"\\underset{z}{\\operatorname{argmax}} C(z).\n",
"\\tag{3}\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 量子近似优化算法\n",
"\n",
"在实际生活中,许多组合优化问题都属于 NP 完全(NP-complete)问题甚至是 NP 困难(NP-hard)问题,这意味着计算机很可能无法高效地解决这样的问题。此时,一种替代方案便是寻找这类问题的近似最优解,而这样的任务通常是可以高效完成的。QAOA 就是一个可以寻找到一个组合优化问题的近似最优解的量子算法。\n",
"\n",
"#### 编码组合优化问题\n",
"\n",
"对于上述的一个组合优化问题,有 $n$ 个比特和 $m$ 个子句。QAOA 算法将这个问题转化为了在 $n$ 个量子比特系统上的优化问题,该量子系统的每个计算基态 $|z\\rangle \\in \\{0,1\\}^n$ 对应着原问题中 $n$ 个比特的一种取值 $z$。同时,对于原问题中的第 $j$ 个子句,我们定义一个对角(diagonal)哈密顿量 $H_{C_j}$ 使其满足\n",
"\n",
"$$\n",
"H_{C_j}|z\\rangle = C_j(z)|z\\rangle.\n",
"\\tag{4}\n",
"$$\n",
"\n",
"具体我们可以通过下式来构造哈密顿量 $H_{C_j}$:\n",
"\n",
"$$\n",
"H_{C_j} = \\sum_{z\\in\\{0,1\\}^n} C_j(z)|z\\rangle\\langle z|.\n",
"\\tag{5}\n",
"$$\n",
"\n",
"例如,假设满足第 $j$ 个子句的取值有 $z^{(1)}$ 和 $z^{(2)}$,那么我们可以定义\n",
"\n",
"$$\n",
"H_{C_j} = |z^{(1)}\\rangle\\langle z^{(1)}| + |z^{(2)}\\rangle\\langle z^{(2)}|.\n",
"\\tag{6}\n",
"$$\n",
"\n",
"由此,QAOA 将组合优化问题的目标函数 $C$ 编码成了 $n$ 个量子比特系统上的哈密顿量\n",
"\n",
"$$\n",
"H_C = \\sum_{j=1}^m w_jH_{C_j},\n",
"\\tag{7}\n",
"$$\n",
"\n",
"并且\n",
"\n",
"$$\n",
"H_C|z\\rangle = \\sum_{j=1}^m w_jH_{C_j}|z\\rangle = \\sum_{j=1}^m w_jC_j(z)|z\\rangle = C(z)|z\\rangle.\n",
"\\tag{8}\n",
"$$\n",
"\n",
"值得注意的是,假设原问题的一个最优解是 $z_\\text{opt}$,那么我们有\n",
"\n",
"$$\n",
"\\langle z_\\text{opt}|H_C|z_\\text{opt}\\rangle = \\langle z_\\text{opt}|C(z_\\text{opt})|z_\\text{opt}\\rangle = C(z_\\text{opt})\\langle z_\\text{opt}|z_\\text{opt}\\rangle = C(z_\\text{opt}).\n",
"\\tag{9}\n",
"$$\n",
"\n",
"因此,原组合优化问题的最优解是哈密顿量 $H_C$ 的一个拥有最大本征值(eigenvalue)的本征态(eigenstate)。此外,对于任意量子态 $|\\psi\\rangle$,\n",
"\n",
"$$\n",
"\\langle\\psi|H_C|\\psi\\rangle \\leq C(z_\\text{opt}),\n",
"\\tag{10}\n",
"$$\n",
"\n",
"且该式取等号当且仅当 $|\\psi\\rangle$ 是几个最优解的叠加态。由式(9)和式(10)可以得到,\n",
"\n",
"$$\n",
"\\max_{|\\psi\\rangle} \\langle\\psi|H_C|\\psi\\rangle = C(z_\\text{opt}),\n",
"\\tag{11}\n",
"$$\n",
"\n",
"并且寻找原组合优化问题的最优解等同于寻找哈密顿量 $H_C$ 的一个拥有最大本征值的本征态,即寻找一个量子态 $|\\psi\\rangle$ 使得\n",
"\n",
"$$\n",
"H_c|\\psi\\rangle = C(z_\\text{opt})|\\psi\\rangle.\n",
"\\tag{12}\n",
"$$\n",
"\n",
"找到这样一个量子态 $|\\psi\\rangle$ 后,它很可能并不是一个计算基态,而是几个计算基态的叠加,这其中的每个计算基态都是原组合优化问题的一个最优解。因此,我们对 $|\\psi\\rangle$ 进行计算基上的测量,便能得到原组合优化问题的一个最优解。\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 寻找近似最优解\n",
"\n",
"尽管将要解决的组合优化问题的目标函数编码成一个量子系统的哈密顿量 $H_C$ 较为简单,但想要根据式(11)从偌大的希尔伯特空间中找到代表最优解的量子态 $|\\psi\\rangle$ 并不容易。为了找到这样一个量子态,我们需要借助另一个哈密顿量\n",
"\n",
"$$\n",
"H_B = \\sum_{j=1}^n X_j,\n",
"\\tag{13}\n",
"$$\n",
"\n",
"其中 $X_j$ 表示作用在第 $j$ 个量子比特上的 Pauli $X$ 门。Pauli $X$ 门的两个本征态分别是 $|+\\rangle$ 和 $|-\\rangle$,它们对应的本征值分别是 $1$ 和 $-1$:\n",
"\n",
"$$\n",
"\\begin{align}\n",
"X|+\\rangle &=\n",
"\\begin{bmatrix}\n",
"0&1\\\\1&0\n",
"\\end{bmatrix}\n",
"\\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\1\n",
"\\end{bmatrix}\n",
"= \\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\1\n",
"\\end{bmatrix}\n",
"= |+\\rangle,\\tag{14}\\\\\n",
"X|-\\rangle &=\n",
"\\begin{bmatrix}\n",
"0&1\\\\1&0\n",
"\\end{bmatrix}\n",
"\\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\-1\n",
"\\end{bmatrix}\n",
"= \\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"-1\\\\1\n",
"\\end{bmatrix}\n",
"= -|-\\rangle.\\tag{15}\n",
"\\end{align}\n",
"$$\n",
"\n",
"因此,$H_B$ 的拥有最大本征值的本征态为\n",
"\n",
"$$\n",
"|s\\rangle \\equiv \\underbrace{|+\\rangle\\otimes\\cdots\\otimes|+\\rangle}_{\\text{共 $n$ 个 }|+\\rangle} = |+\\rangle^{\\otimes n}.\n",
"\\tag{16}\n",
"$$\n",
"\n",
"我们将把这个量子态 $|s\\rangle$ 作为算法的初始态。构造出哈密顿量 $H_C$ 和 $H_B$ 后,我们就可以开始寻找原组合优化问题的一个近似最优解了。根据哈密顿量 $H_C$ 和 $H_B$,分别定义酉变换\n",
"\n",
"$$\n",
"U_C(\\gamma) = e^{-i\\gamma H_C}\n",
"\\tag{17}\n",
"$$\n",
"\n",
"和酉变换\n",
"\n",
"$$\n",
"U_B(\\beta) = e^{-i\\beta H_B},\n",
"\\tag{18}\n",
"$$\n",
"\n",
"其中 $\\gamma$ 和 $\\beta$ 是实数,为可调节的参数。给定任意一个整数 $p\\geq1$ 以及参数 $\\vec{\\gamma}=(\\gamma_1,\\dots,\\gamma_p)$ 和 $\\vec{\\beta}=(\\beta_1,\\dots,\\beta_p)$,我们定义\n",
"\n",
"$$\n",
"|\\vec{\\gamma},\\vec{\\beta}\\rangle = U_B(\\beta_p)U_C(\\gamma_p)\\cdots U_B(\\beta_1)U_C(\\gamma_1)|s\\rangle.\n",
"\\tag{19}\n",
"$$\n",
"\n",
"可以看到,整数 $p$ 表示用到的 $U_C,U_B$ 的层数,即分别将 $U_C$ 和 $U_B$ 交替地作用在初始态 $|s\\rangle$ 上 $p$ 次。我们记 $F_p(\\vec{\\gamma},\\vec{\\beta})$ 为哈密顿量 $H_C$ 在式(19)的量子态下的期望值,\n",
"\n",
"$$\n",
"F_p(\\vec{\\gamma},\\vec{\\beta}) = \\langle\\vec{\\gamma},\\vec{\\beta}|H_C|\\vec{\\gamma},\\vec{\\beta}\\rangle.\n",
"\\tag{20}\n",
"$$\n",
"\n",
"通过调整参数 $\\vec{\\gamma},\\vec{\\beta}$,我们可以得到\n",
"\n",
"$$\n",
"M_p = \\max_{\\vec{\\gamma},\\vec{\\beta}} F_p(\\vec{\\gamma},\\vec{\\beta})\n",
"\\tag{21}\n",
"$$\n",
"\n",
"作为给定层数 $p$ 下的近似最优解。至此,我们将寻找量子态 $|\\psi\\rangle$ 的问题转变为了搜寻参数 $\\vec{\\gamma},\\vec{\\beta}$ 的问题。值得注意的是,$p$ 层酉变换 $U_C,U_B$ 的表达能力强于 $p-1$ 层的表达能力,因此\n",
"\n",
"$$\n",
"M_p \\geq M_{p-1}.\n",
"\\tag{22}\n",
"$$\n",
"\n",
"事实上,当 $p$ 足够大时,\n",
"\n",
"$$\n",
"\\lim_{p\\to\\infty} M_p = \\max_z C(z).\n",
"\\tag{23}\n",
"$$\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 解码量子答案\n",
"\n",
"在上一段中,尽管我们将寻找量子态 $|\\psi\\rangle$ 转变为了寻找参数化量子态 $|\\vec{\\gamma},\\vec{\\beta}\\rangle$ 以方便我们的搜索,但同时我们也缩小了搜索的空间,也就是说,在给定层数 $p$ 的情况下,可能并不存在参数 $\\vec{\\gamma},\\vec{\\beta}$ 使得 $F_p(\\vec{\\gamma},\\vec{\\beta}) = C(z_\\text{opt})$。假设参数 $\\vec{\\gamma}^*$ 和 $\\vec{\\beta}^*$ 使得 $F_p$ 最大,即 $F_p(\\vec{\\gamma}^*,\\vec{\\beta}^*) = M_p$,那么在理想情况下量子态 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 包含了最优解的信息。但要注意的是,这里只使用了 $p$ 层,因此很可能 $M_p < C(z_\\text{opt})$。因此,一般情况下 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 只包含了近似最优解的信息。进一步地,我们假设量子态 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 是 $l$ 个计算基态的叠加态,即\n",
"\n",
"$$\n",
"|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle = c_1|z^{(1)}\\rangle + \\cdots + c_l|z^{(l)}\\rangle.\n",
"\\tag{24}\n",
"$$\n",
"\n",
"通常情况下,一个态 $|z^{(j)}\\rangle$ 在计算基上测量得到的概率 $|c_j|^2$ 越大,意味着其对应的比特串 $z^{(j)}$ 是最优解的可能性越大。那么我们制备 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 并测量,得到一个比特串 $z$ 并计算 $C(z)$ 的值。重复多次这个过程,便能得到一个 $z$ 使得 $C(z)$ 接近甚至超过 $M_p$。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 绝热定理\n",
"\n",
"为什么可以用上述的方法来构造量子态 $|\\vec{\\gamma},\\vec{\\beta}\\rangle$? QAOA 试图找到一个优化问题的近似最优解,一个与之类似的算法是量子绝热算法 [2](Quantum Adiabatic Algorithm, QAA)。但不同的是,QAA 是为了找到优化问题的最优解而非近似最优解。与 QAOA 类似,QAA 将一个优化问题转化为了求一个哈密顿量的基态的问题,并利用绝热定理(adiabatic theorem)对其求解。考虑一个量子系统的哈密顿量\n",
"\n",
"$$\n",
"H(t) = (1-\\frac tT)H_B + \\frac tT H_C,\n",
"\\tag{25}\n",
"$$\n",
"\n",
"初始时,时间 $t=0$,该系统的哈密顿量为 $H(0) = H_B$。随着时间的流逝,该系统的哈密顿量逐渐由 $H_B$ 变为 $H_C$。当 $t=T$ 时,该系统的哈密顿量变为 $H(T) = H_C$。量子力学中的绝热定理告诉我们,如果初始时该系统处于 $H_B$ 的一个本征态,那么只要时间 $T$ 足够长,当系统的哈密顿量完全演化为 $H_C$ 时,该系统会处于 $H_C$ 的对应能级的本征态。因此,如果初始时该系统处于 $|s\\rangle$,即 $H_B$ 拥有最大本征值的本征态,经过足够长的演化时间 $T$,该系统的量子态会变为 $H_C$ 拥有最大本征值的本征态。[3]\n",
"\n",
"一种模拟哈密顿量 $H(t)$ 随着时间 $t$ 演化的方法便是交替地在该量子系统上作用酉变换 $U_C(\\gamma)$ 和 $U_B(\\beta)$,而模拟的精度取决于 $\\gamma,\\beta$ 的取值。另外,为了让系统的演化遵循绝热定理,需要足够长的演化时间,所以要求 $p$ 的取值足够大。因此,结合公式(22)可以推出公式(23)中的结论。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-06T07:12:18.621281Z",
"start_time": "2021-01-06T07:12:18.308211Z"
}
},
"source": [
"### 示例:QAOA 求解最大割问题\n",
"\n",
"最大割问题(Max-Cut Problem)是图论中常见的一个组合优化问题,在统计物理学和电路设计中都有重要应用。最大割问题是一个 NP 完全问题,因此目前并不存在一个高效的算法能完美地解决该问题。\n",
"## Overview\n",
"\n",
"#### 最大割问题\n",
"In the [tutorial on Quantum Approximate Optimization Algorithm](./QAOA_EN.ipynb), we talked about how to encode a classical combinatorial optimization problem into a quantum optimization problem and slove it with Quantum Approximate Optimization Algorithm [1] (QAOA). In this tutorial, we will take the Max-Cut Problem as an example to further elaborate on QAOA.\n",
"\n",
"在图论中,一个图是由一对集合 $G=(V, E)$ 表示,其中集合 $V$ 中的元素为该图的顶点,集合 $E$ 中的每个元素是一对顶点,表示连接这两个顶点的一条边。例如下方图片中的图可以由 $V=\\{0,1,2,3\\}$ 和 $E=\\{(0,1),(1,2),(2,3),(3,0)\\}$ 表示。\n",
"### Max-Cut Problem\n",
"\n",
"![G](figures/qaoa-fig-maxcut_g.png \"图 1:一个有四个顶点和四条边的图\")\n",
"<div style=\"text-align:center\">图 1:一个有四个顶点和四条边的图 </div>\n",
"The Max-Cut Problem is a common combinatorial optimization problem in graph theory, and it has important applications in statistical physics and circuit design. The maximum cut problem is an NP-hard problem, so there is no efficient algorithm that can solve this problem perfectly.\n",
"\n",
"In graph theory, a graph is represented by a pair of sets $G=(V, E)$, where the elements in the set $V$ are the vertices of the graph, and each element in the set $E$ is a pair of vertices, representing an edge connecting these two vertices. For example, the graph in the figure below is represented by $V=\\{0,1,2,3\\}$ and $E=\\{(0,1),(1,2),(2,3),(3, 0)\\}$.\n",
"\n",
"一个图上的割(cut)是指将该图的顶点集 $V$ 分割成两个互不相交的集合的一种划分,每个割都对应一个边的集合,这些边的两个顶点被划分在不同的集合中。于是我们可以将这个割的大小定义为这个边的集合的大小,即被割开的边的条数。最大割问题就是要找到一个割使得被割开的边的条数最多。图 2 展示了图 1 中图的一个最大割,该最大割的大小为 $4$,即割开了图中所有的边。\n",
"![G](figures/maxcut-fig-maxcut_g.png \"Figure 1: A graph with four vertices and four edges\")\n",
"<div style=\"text-align:center\">Figure 1: A graph with four vertices and four edges </div>\n",
"\n",
"![Max cut on G](figures/qaoa-fig-maxcut_cut.png \"图 2:图 1 中图的一个最大割\")\n",
"<div style=\"text-align:center\">图 2:图 1 中图的一个最大割 </div>\n",
"A cut on a graph refers to a partition of the graph's vertex set $V$ into two disjoint sets. Each cut corresponds to a set of edges, in which the two vertices of each edge are divided into different sets. So we can define the size of this cut as the size of this set of edges, that is, the number of edges being cut. The Max-Cut Problem is to find a cut that maximizes the number of edges being cut. Figure 2 shows a maximum cut of the graph in Figure 1. The size of the maximum cut is $4$, which means that all edges in the graph are cut.\n",
"\n",
"![Max cut on G](figures/maxcut-fig-maxcut_cut.png \"Figure 2: A maximum cut of the graph in Figure 1\")\n",
"<div style=\"text-align:center\">Figure 2: A maximum cut of the graph in Figure 1 </div>\n",
"\n",
"假设输入的图 $G=(V, E)$ 有 $n=|V|$ 个顶点和 $m=|E|$ 条边,那么我们可以将最大割问题描述为 $n$ 个比特和 $m$ 个子句的组合优化问题。每个比特对应图 $G$ 中的一个顶点 $v$,其取值 $z_v$ 为 $0$ 或 $1$,分别对应该顶点属于集合 $S_{0}$ 或 $S_{1}$,因此这 $n$ 个比特的每种取值 $z$ 都对应一个割。每个子句则对应图 $G$ 中的一条边 $(u,v)$,一个子句要求其对应的边连接的两个顶点的取值不同,即 $z_u\\neq z_v$,表示该条边被割开。也就是说,当该条边连接这的两个顶点被割划分到不同的集合上时,我们说该子句被满足。因此,对于图 $G$ 中的每条边 $(u,v)$,我们有\n",
"Assuming that the input graph $G=(V, E)$ has $n=|V|$ vertices and $m=|E|$ edges, we can describe the Max-Cut Problem as a combinatorial optimization problem with $n$ bits and $m$ clauses. Each bit corresponds to a vertex $v$ in the graph $G$, and its value $z_v$ is $0$ or $1$, corresponding to the vertex belonging to the set $S_{0}$ or $S_{1}$, respectively. Thus, each value $z$ of these $n$ bits corresponds to a distinct cut. Each clause corresponds to an edge $(u,v)$ in the graph $G$. A clause requires that the two vertices connected by its corresponding edge take different values, namely $z_u\\neq z_v$, which means the edge is cut. In other words, when the two vertices connected by the edge are divided into different sets, we say that the clause is satisfied. Therefore, for each edge $(u,v)$ in the graph $G$, we have\n",
"\n",
"$$\n",
"C_{(u,v)}(z) = z_u+z_v-2z_uz_v,\n",
"\\tag{26}\n",
"\\tag{1}\n",
"$$\n",
"\n",
"其中 $C_{(u,v)}(z) = 1$ 当且仅当该条边被割开。否则,该函数等于 $0$。整个组合优化问题的目标函数是\n",
"where $C_{(u,v)}(z) = 1$ if and only if the edge is cut. Otherwise, the function is equal to $0$. The objective function of the entire combinatorial optimization problem is\n",
"\n",
"$$\n",
"C(z) = \\sum_{(u,v)\\in E}C_{(u,v)}(z) = \\sum_{(u,v)\\in E}z_u+z_v-2z_uz_v.\n",
"\\tag{27}\n",
"\\tag{2}\n",
"$$\n",
"\n",
"因此,解决最大割问题就是要找到一个取值 $z$ 使得公式(27)中的目标函数最大。\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 编码最大割问题\n",
"Therefore, to solve the maximum cut problem is to find a value $z$ that maximizes the objective function in equation (2).\n",
"\n",
"这里我们以最大割问题为例来进一步阐述 QAOA。为了将最大割问题转化为一个量子问题,我们要用到 $n$ 个量子比特,每个量子比特对应图 $G$ 中的一个顶点。一个量子比特处于量子态 $|0\\rangle$ 或 $|1\\rangle$,表示其对应的顶点属于集合 $S_{0}$ 或 $S_{1}$。值得注意的是,$|0\\rangle$ 和 $|1\\rangle$ 是 Pauli $Z$ 门的两个本征态,并且它们的本征值分别为 $1$ 和 $-1$,即\n",
"### Encoding Max-Cut Problem\n",
"\n",
"Here we take the Max-Cut Problem as an example to further elaborate on QAOA. In order to transform the Max-Cut Problem into a quantum problem, we need to use $n$ qubits, where each qubit corresponds to a vertex in the graph $G$. A qubit being in a quantum state $|0\\rangle$ or $|1\\rangle$ indicates that its corresponding vertex belongs to the set $S_{0}$ or $S_{1}$, respectively. It is worth noting that $|0\\rangle$ and $|1\\rangle$ are the two eigenstates of Pauli $Z$ gate, and their eigenvalues are respectively $1$ and $-1$, namely\n",
"\n",
"$$\n",
"\\begin{align}\n",
"Z|0\\rangle&=|0\\rangle,\\tag{28}\\\\\n",
"Z|1\\rangle&=-|1\\rangle.\\tag{29}\n",
"Z|0\\rangle&=|0\\rangle,\\tag{3}\\\\\n",
"Z|1\\rangle&=-|1\\rangle.\\tag{4}\n",
"\\end{align}\n",
"$$\n",
"\n",
"因此我们可以使用 Pauli $Z$ 门来构建该最大割问题的哈密顿量 $H_C$。因为通过映射 $f(x):x\\to(x+1)/2$ 可以将 $-1$ 映射到 $0$ 上 并且仍将 $1$ 映射到 $1$ 上,所以我们可以将式(27)中的 $z$ 替换为 $(Z+I)/2$($I$ 是单位矩阵),得到原问题目标函数对应的哈密顿量\n",
"Therefore, we can use Pauli $Z$ gate to construct the Hamiltonian $H_C$ of the Max-Cut Problem. Because mapping $f(x):x\\to(x+1)/2$ maps $-1$ to $0$ and $1$ to $1$, we can replace $z$ in equation (2) with $(Z+I)/2$ ($I$ is the identity matrix) to get the Hamiltonian corresponding to the objective function of the original problem:\n",
"\n",
"$$\n",
"\\begin{align}\n",
"H_C &= \\sum_{(u,v)\\in E} \\frac{Z_u+I}{2} + \\frac{Z_v+I}{2} - 2\\cdot\\frac{Z_u+I}{2}\\frac{Z_v+I}{2}\\tag{30}\\\\\n",
"&= \\sum_{(u,v)\\in E} \\frac{Z_u+Z_v+2I - (Z_uZ_v+Z_u+Z_v+I)}{2}\\tag{31}\\\\\n",
"&= \\sum_{(u,v)\\in E} \\frac{I - Z_uZ_v}{2}.\\tag{32}\n",
"H_C &= \\sum_{(u,v)\\in E} \\frac{Z_u+I}{2} + \\frac{Z_v+I}{2}-2\\cdot\\frac{Z_u+I}{2} \\frac{Z_v+I}{2}\\tag{5}\\\\\n",
"&= \\sum_{(u,v)\\in E} \\frac{Z_u+Z_v+2I-(Z_uZ_v+Z_u+Z_v+I)}{2}\\tag{6}\\\\\n",
"&= \\sum_{(u,v)\\in E} \\frac{I-Z_uZ_v}{2}.\\tag{7}\n",
"\\end{align}\n",
"$$\n",
"\n",
"该哈密顿量关于一个量子态 $|\\psi\\rangle$ 的期望值为\n",
"The expected value of this Hamiltonian for a quantum state $|\\psi\\rangle$ is\n",
"\n",
"$$\n",
"\\begin{align}\n",
"\\langle\\psi|H_C|\\psi\\rangle &= \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{I - Z_uZ_v}{2}|\\psi\\rangle\\tag{33}\\\\\n",
"&= \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{I}{2}|\\psi\\rangle - \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{Z_uZ_v}{2}|\\psi\\rangle\\tag{34}\\\\\n",
"&= \\frac{|E|}{2} - \\frac{1}{2}\\langle\\psi|\\sum_{(u,v)\\in E} Z_uZ_v|\\psi\\rangle.\\tag{35}\n",
"\\langle\\psi|H_C|\\psi\\rangle &= \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{I-Z_uZ_v}{2}|\\psi\\rangle\\tag{8} \\\\\n",
"&= \\langle\\psi|\\sum_{(u,v)\\in E} \\frac{I}{2}|\\psi\\rangle-\\langle\\psi|\\sum_{(u,v)\\in E} \\frac{Z_uZ_v}{2}|\\psi\\rangle\\tag{9}\\\\\n",
"&= \\frac{|E|}{2}-\\frac{1}{2}\\langle\\psi|\\sum_{(u,v)\\in E} Z_uZ_v|\\psi\\rangle.\\tag{10}\n",
"\\end{align}\n",
"$$\n",
"\n",
"如果我们记\n",
"If we define\n",
"\n",
"$$\n",
"H_D = -\\sum_{(u,v)\\in E} Z_uZ_v,\n",
"\\tag{36}\n",
"\\tag{11}\n",
"$$\n",
"\n",
"那么找到量子态 $|\\psi\\rangle$ 使得 $\\langle\\psi|H_C|\\psi\\rangle$ 最大等价于找到量子态 $|\\psi\\rangle$ 使得 $\\langle\\psi|H_D|\\psi\\rangle$ 最大。\n",
"\n"
"then finding the quantum state $|\\psi\\rangle$ that maximizes $\\langle\\psi|H_C|\\psi\\rangle$ is equivalent to finding the quantum state $|\\psi\\rangle$ such that $\\langle\\psi|H_D|\\psi \\rangle$ is the largest."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Paddle Quantum 实现\n",
"## Paddle Quantum Implementation\n",
"\n",
"我们以最大割问题为例,用量桨实现 QAOA 算法求解最大割问题。有许多方法可以找到参数 $\\vec{\\gamma},\\vec{\\beta}$,我们这里使用经典机器学习中的梯度下降方法。\n",
"Now, let's implement QAOA with Paddle Quantum to solve the Max-Cut Problem. There are many ways to find the parameters $\\vec{\\gamma},\\vec{\\beta}$. Here we use the gradient descent method in classical machine learning.\n",
"\n",
"要在量桨上实现 QAOA,首先要做的便是加载需要用到的包。其中 `networkx` 包可以帮助我们方便地处理图。\n",
"\n"
"To implement QAOA with Paddle Quantum, the first thing to do is to import the required packages. Among them, the `networkx` package can help us handle graphs conveniently."
]
},
{
......@@ -371,19 +114,48 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:04:55.556042Z",
"start_time": "2021-02-22T11:04:55.546040Z"
"end_time": "2021-04-30T09:07:36.250220Z",
"start_time": "2021-04-30T09:07:36.223934Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"<style>pre { white-space: pre !important; }</style>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.core.display import HTML\n",
"display(HTML(\"<style>pre { white-space: pre !important; }</style>\"))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-30T09:07:40.001750Z",
"start_time": "2021-04-30T09:07:36.983994Z"
}
},
"outputs": [],
"source": [
"# 加载量桨、飞桨的相关模块\n",
"# Import related modules from Paddle Quantum and PaddlePaddle\n",
"import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.utils import pauli_str_to_matrix\n",
"\n",
"# 加载额外需要用到的包\n",
"# Import additional packages needed\n",
"import numpy as np\n",
"from numpy import pi as PI\n",
"import matplotlib.pyplot as plt\n",
"import networkx as nx"
]
......@@ -392,16 +164,16 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"接下来,我们生成该最大割问题中的图 $G$。为了运算方便,这里的顶点从 $0$ 开始计数。\n"
"Next, we generate the graph $G$ in the Max-Cut Problem. For the convenience of computation, the vertices here are labeled starting from $0$."
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:04:58.341557Z",
"start_time": "2021-02-22T11:04:58.266794Z"
"end_time": "2021-04-30T09:07:40.192343Z",
"start_time": "2021-04-30T09:07:40.007013Z"
}
},
"outputs": [
......@@ -417,7 +189,7 @@
}
],
"source": [
"# n 是图 G 的顶点数,同时也是量子比特的个数\n",
"# n is the number of vertices in the graph G, which is also the number of qubits\n",
"n = 4\n",
"G = nx.Graph()\n",
"V = range(n)\n",
......@@ -425,7 +197,7 @@
"E = [(0, 1), (1, 2), (2, 3), (3, 0)]\n",
"G.add_edges_from(E)\n",
"\n",
"# 将生成的图 G 打印出来\n",
"# Print out the generated graph G\n",
"pos = nx.circular_layout(G)\n",
"options = {\n",
" \"with_labels\": True,\n",
......@@ -446,18 +218,18 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### 编码哈密顿量\n",
"### Encoding Hamiltonian\n",
"\n",
"量桨中,哈密顿量可以以 `list` 的形式输入。这里我们构建式(36)中的哈密顿量 $H_D$。"
"In Paddle Quantum, a Hamiltonian can be input in the form of `list`. Here we construct the Hamiltonian $H_D$ in equation (11)."
]
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:05:01.414498Z",
"start_time": "2021-02-22T11:05:01.409511Z"
"end_time": "2021-04-30T09:07:40.206426Z",
"start_time": "2021-04-30T09:07:40.197339Z"
}
},
"outputs": [
......@@ -470,10 +242,10 @@
}
],
"source": [
"# 以 list 的形式构建哈密顿量 H_D\n",
"# Construct the Hamiltonian H_D in the form of list\n",
"H_D_list = []\n",
"for (u, v) in E:\n",
" H_D_list.append([-1.0, 'z'+str(u) + ',z' + str(v)])\n",
" H_D_list.append([-1.0,'z'+str(u) +',z' + str(v)])\n",
"print(H_D_list)"
]
},
......@@ -481,23 +253,23 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"可以看到,在这个例子中,哈密顿量 $H_D$ 为\n",
"As you can see, in this example, the Hamiltonian $H_D$ is\n",
"\n",
"$$\n",
"H_D = -Z_0Z_1 - Z_1Z_2 - Z_2Z_3 - Z_3Z_0.\n",
"\\tag{37}\n",
"H_D = -Z_0Z_1-Z_1Z_2-Z_2Z_3-Z_3Z_0.\n",
"\\tag{12}\n",
"$$\n",
"\n",
"我们可以查看哈密顿量 $H_D$ 的矩阵形式,并且获取它的本征值信息:"
"We can view the matrix form of the Hamiltonian $H_D$ and get information of its eigenvalues:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:05:03.494792Z",
"start_time": "2021-02-22T11:05:03.488812Z"
"end_time": "2021-04-30T09:07:40.501135Z",
"start_time": "2021-04-30T09:07:40.491760Z"
}
},
"outputs": [
......@@ -511,11 +283,11 @@
}
],
"source": [
"# 将哈密顿量 H_D 从 list 形式转为矩阵形式\n",
"# Convert Hamiltonian H_D from list form to matrix form\n",
"H_D_matrix = pauli_str_to_matrix(H_D_list, n)\n",
"# 取出 H_D 对角线上的元素\n",
"# Take out the elements on the diagonal of H_D\n",
"H_D_diag = np.diag(H_D_matrix).real\n",
"# 获取 H_D 的最大本征值\n",
"# Get the maximum eigenvalue of H_D\n",
"H_max = np.max(H_D_diag)\n",
"\n",
"print(H_D_diag)\n",
......@@ -526,54 +298,53 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### 搭建 QAOA 电路\n",
"### Building the QAOA circuit\n",
"\n",
"前面我们介绍了 QAOA 需要将两个酉变换 $U_C(\\gamma)$ 和 $U_B(\\beta)$ 交替地作用在初始态 $|s\\rangle = |+\\rangle^{\\otimes n}$ 上。在这里,我们使用量桨中提供的量子门和量子电路模板搭建出一个量子电路来实现这一步骤。要注意的是,在最大割问题中,我们将最大化哈密顿量 $H_C$ 的期望值的问题简化为了最大化哈密顿量 $H_D$ 的期望值的问题,因此要用到的酉变换也就变成了 $U_D(\\gamma)$ 和 $U_B(\\beta)$。通过交替地摆放两个参数可调的电路模块,我们得以搭建QAOA电路\n",
"Earlier we introduced that QAOA needs to apply two unitary transformations $U_C(\\gamma)$ and $U_B(\\beta)$ alternately on the initial state $|s\\rangle = |+\\rangle^{\\otimes n}$. Here, we use the quantum gates and quantum circuit templates provided in Paddle Quantum to build a quantum circuit to achieve this step. It should be noted that in the Max-Cut Problem, we simplify the problem of maximizing the expected value of the Hamiltonian $H_C$ to the problem of maximizing the expected value of the Hamiltonian $H_D$, so the unitary transformations to be used are $U_D(\\gamma)$ and $U_B(\\beta)$. By alternately placing two circuit modules with adjustable parameters, we are able to build a QAOA circuit\n",
"\n",
"$$\n",
"U_B(\\beta_p)U_D(\\gamma_p)\\cdots U_B(\\beta_1)U_D(\\gamma_1),\n",
"\\tag{38}\n",
"\\tag{13}\n",
"$$\n",
"\n",
"其中,$U_D(\\gamma) = e^{-i\\gamma H_D}$ 可以由下图中的电路搭建实现。另一个酉变换 $U_B(\\beta)$ 则等价于在每个量子比特上作用一个 $R_x$ 门。\n",
"where $U_D(\\gamma) = e^{-i\\gamma H_D}$ can be constructed with the circuit in the figure below. Another unitary transformation $U_B(\\beta)$ is equivalent to applying a $R_x$ gate to each qubit.\n",
"\n",
"![U_D circuit](figures/qaoa-fig-cir_ud.png \"图 3:酉变换 $e^{i\\gamma Z\\otimes Z}$ 的量子电路实现\")\n",
"<div style=\"text-align:center\">图 3:酉变换 $e^{i\\gamma Z\\otimes Z}$ 的量子电路实现 </div>\n",
"![U_D circuit](figures/maxcut-fig-cir_ud.png \"Figure 3: Quantum circuit of unitary transformation $e^{i\\gamma Z\\otimes Z}$\")\n",
"<div style=\"text-align:center\">Figure 3: Quantum circuit of unitary transformation $e^{i\\gamma Z\\otimes Z}$</div>\n",
"\n",
"Therefore, the quantum circuit that realizes a layer of unitary transformation $U_B(\\beta)U_D(\\gamma)$ is shown in Figure 4.\n",
"\n",
"因此,实现一层酉变换 $U_B(\\beta)U_D(\\gamma)$ 的量子电路如图 4 所示。\n",
"![U_BU_D circuit](figures/maxcut-fig-cir_ubud.png \"Figure 4: Quantum circuit of unitary transformation $U_B(\\beta)U_D(\\gamma)$\")\n",
"<div style=\"text-align:center\">Figure 4: Quantum circuit of unitary transformation $U_B(\\beta)U_D(\\gamma)$ </div>\n",
"\n",
"![U_BU_D circuit](figures/qaoa-fig-cir_ubud.png \"图 4:酉变换 $U_B(\\beta)U_D(\\gamma)$ 的量子电路实现\")\n",
"<div style=\"text-align:center\">图 4:酉变换 $U_B(\\beta)U_D(\\gamma)$ 的量子电路实现 </div>\n",
"\n",
"量桨中,电路运行前每个量子比特默认的初始状态为 $|0\\rangle$(可以通过输入参数来自定义初始状态),我们可以通过添加一层 Hadamard 门使每个量子比特的状态由 $|0\\rangle$ 变为 $|+\\rangle$,由此得到 QAOA 要求的初始态 $|s\\rangle = |+\\rangle^{\\otimes n}$。在量桨中,可以通过调用 `superposition_layer()` 在量子电路中添加一层 Hadamard 门。"
"In Paddle Quantum, the default initial state of each qubit is $|0\\rangle$ (the initial state can be customized by input parameters). We can add a layer of Hadamard gates to change the state of each qubit from $|0\\rangle$ to $|+\\rangle$ so that we get the initial state $|s\\rangle = |+\\rangle^{\\otimes n}$ required by QAOA. In Paddle Quantum, we can add a layer of Hadamard gates to the quantum circuit by calling `superposition_layer()`."
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:05:09.921594Z",
"start_time": "2021-02-22T11:05:09.914611Z"
"end_time": "2021-04-30T09:07:41.987233Z",
"start_time": "2021-04-30T09:07:41.977734Z"
}
},
"outputs": [],
"source": [
"def circuit_QAOA(p, gamma, beta):\n",
" # 初始化 n 个量子比特的量子电路\n",
" # Initialize the quantum circuit of n qubits\n",
" cir = UAnsatz(n)\n",
" # 制备量子态 |s>\n",
" # Prepare quantum state |s>\n",
" cir.superposition_layer()\n",
" # 搭建 p 层电路\n",
" # Build a circuit with p layers\n",
" for layer in range(p):\n",
" # 搭建 U_D 的电路\n",
" # Build the circuit of U_D\n",
" for (u, v) in E:\n",
" cir.cnot([u, v])\n",
" cir.rz(gamma[layer], v)\n",
" cir.cnot([u, v])\n",
"\n",
" # 搭建 U_B 的电路,即添加一层 R_x 门\n",
" # Build the circuit of U_B, that is, add a layer of R_x gates\n",
" for v in V:\n",
" cir.rx(beta[layer], v)\n",
"\n",
......@@ -584,58 +355,59 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"搭建 QAOA 量子电路的工作完成后,如果运行该量子电路,得到的输出态为\n",
"After running the constructed QAOA quantum circuit, we obtain the output state\n",
"\n",
"$$\n",
"|\\vec{\\gamma},\\vec{\\beta}\\rangle = U_B(\\beta_p)U_D(\\gamma_p)\\cdots U_B(\\beta_1)U_D(\\gamma_1)|s\\rangle.\n",
"\\tag{39}\n",
"$$\n",
"\n",
"### 计算损失函数\n",
"\\tag{14}\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Calculating the loss function\n",
"\n",
"由上一步搭建的电路的输出态,我们可以计算最大割问题的目标函数\n",
"From the output state of the circuit built in the previous step, we can calculate the objective function of the maximum cut problem\n",
"\n",
"$$\n",
"F_p(\\vec{\\gamma},\\vec{\\beta}) = \\langle\\vec{\\gamma},\\vec{\\beta}|H_D|\\vec{\\gamma},\\vec{\\beta}\\rangle.\n",
"\\tag{40}\n",
"\\tag{15}\n",
"$$\n",
"\n",
"要最大化该目标函数等价于最小化 $-F_p$。因此我们定义 $L(\\vec{\\gamma},\\vec{\\beta}) = -F_p(\\vec{\\gamma},\\vec{\\beta})$ 为损失函数,即要最小化的函数,然后利用经典的优化算法寻找最优参数 $\\vec{\\gamma},\\vec{\\beta}$。下面的代码给出了通过量桨和飞桨搭建的完整 QAOA 网络:"
"To maximize the objective function is equivalent to minimizing $-F_p$. Therefore, we define $L(\\vec{\\gamma},\\vec{\\beta}) = -F_p(\\vec{\\gamma},\\vec{\\beta})$ as the loss function, that is, the function to be minimized. Then, we use a classical optimization algorithm to find the optimal parameters $\\vec{\\gamma},\\vec{\\beta}$. The following code shows a complete QAOA network built with Paddle Quantum and PaddlePaddle:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:08:23.218571Z",
"start_time": "2021-02-22T11:08:23.211589Z"
"end_time": "2021-04-30T09:07:43.856891Z",
"start_time": "2021-04-30T09:07:43.846753Z"
}
},
"outputs": [],
"source": [
"class Net(paddle.nn.Layer):\n",
" def __init__(\n",
" self,\n",
" p,\n",
" dtype=\"float64\",\n",
" ):\n",
" def __init__(self, p, dtype=\"float64\",):\n",
" super(Net, self).__init__()\n",
"\n",
" self.p = p\n",
" self.gamma = self.create_parameter(shape=[self.p], \n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*np.pi),\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*np.pi),\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI), \n",
" dtype=dtype, is_bias=False)\n",
"\n",
" def forward(self):\n",
" # 定义 QAOA 的量子电路\n",
" # Define QAOA's quantum circuit\n",
" cir = circuit_QAOA(self.p, self.gamma, self.beta)\n",
" # 运行该量子电路\n",
" # Run the quantum circuit\n",
" cir.run_state_vector()\n",
" # 计算损失函数\n",
" # Calculate the loss function\n",
" loss = -cir.expecval(H_D_list)\n",
"\n",
" return loss, cir"
......@@ -645,42 +417,42 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### 训练量子神经网络\n",
"定义好了用于 QAOA 的量子神经网络后,我们使用梯度下降的方法来更新其中的参数,使得式(40)的期望值最大。"
"### Training quantum neural network\n",
"\n",
"After defining the quantum neural network for QAOA, we use the gradient descent method to update the parameters in the network to maximize the expected value in equation (15)."
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:10:08.324892Z",
"start_time": "2021-02-22T11:10:08.321896Z"
"end_time": "2021-04-30T09:07:44.907375Z",
"start_time": "2021-04-30T09:07:44.901678Z"
}
},
"outputs": [],
"source": [
"p = 4 # 量子电路的层数\n",
"ITR = 120 # 训练迭代的次数\n",
"LR = 0.1 # 基于梯度下降的优化方法的学习率\n",
"SEED = 1024 #设置全局随机数种子"
"p = 4 # Number of layers in the quantum circuit\n",
"ITR = 120 # Number of training iterations\n",
"LR = 0.1 # Learning rate of the optimization method based on gradient descent\n",
"SEED = 1024 # Set global RNG seed "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"这里,我们在飞桨中优化上面定义的网络。\n",
"\n"
"Here, we optimize the network defined above in PaddlePaddle."
]
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 10,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:11:28.060342Z",
"start_time": "2021-02-22T11:11:09.448098Z"
"end_time": "2021-04-30T09:10:00.930860Z",
"start_time": "2021-04-30T09:09:27.825635Z"
}
},
"outputs": [
......@@ -688,21 +460,31 @@
"name": "stdout",
"output_type": "stream",
"text": [
"iter: 10 loss: -3.8886\n",
"iter: 20 loss: -3.9134\n",
"iter: 30 loss: -3.9659\n",
"iter: 40 loss: -3.9906\n",
"iter: 50 loss: -3.9979\n",
"iter: 60 loss: -3.9993\n",
"iter: 70 loss: -3.9998\n",
"iter: 80 loss: -3.9999\n",
"iter: 90 loss: -4.0000\n",
"iter: 100 loss: -4.0000\n",
"iter: 110 loss: -4.0000\n",
"iter: 120 loss: -4.0000\n",
"优化后的参数 gamma:\n",
"iter: 10 loss: -3.8886\n",
"iter: 20 loss: -3.9134\n",
"iter: 30 loss: -3.9659\n",
"iter: 40 loss: -3.9906\n",
"iter: 50 loss: -3.9979\n",
"iter: 60 loss: -3.9993\n",
"iter: 70 loss: -3.9998\n",
"iter: 80 loss: -3.9999\n",
"iter: 90 loss: -4.0000\n",
"iter: 100 loss: -4.0000\n",
"iter: 110 loss: -4.0000\n",
"iter: 120 loss: -4.0000\n",
"\n",
"The trained circuit:\n",
"--H----*-----------------*--------------------------------------------------X----Rz(3.140)----X----Rx(0.824)----*-----------------*--------------------------------------------------X----Rz(0.737)----X----Rx(2.506)----*-----------------*--------------------------------------------------X----Rz(4.999)----X----Rx(4.854)----*-----------------*--------------------------------------------------X----Rz(0.465)----X----Rx(1.900)--\n",
" | | | | | | | | | | | | | | | | \n",
"--H----X----Rz(3.140)----X----*-----------------*---------------------------|-----------------|----Rx(0.824)----X----Rz(0.737)----X----*-----------------*---------------------------|-----------------|----Rx(2.506)----X----Rz(4.999)----X----*-----------------*---------------------------|-----------------|----Rx(4.854)----X----Rz(0.465)----X----*-----------------*---------------------------|-----------------|----Rx(1.900)--\n",
" | | | | | | | | | | | | | | | | \n",
"--H---------------------------X----Rz(3.140)----X----*-----------------*----|-----------------|----Rx(0.824)---------------------------X----Rz(0.737)----X----*-----------------*----|-----------------|----Rx(2.506)---------------------------X----Rz(4.999)----X----*-----------------*----|-----------------|----Rx(4.854)---------------------------X----Rz(0.465)----X----*-----------------*----|-----------------|----Rx(1.900)--\n",
" | | | | | | | | | | | | | | | | \n",
"--H--------------------------------------------------X----Rz(3.140)----X----*-----------------*----Rx(0.824)--------------------------------------------------X----Rz(0.737)----X----*-----------------*----Rx(2.506)--------------------------------------------------X----Rz(4.999)----X----*-----------------*----Rx(4.854)--------------------------------------------------X----Rz(0.465)----X----*-----------------*----Rx(1.900)--\n",
" \n",
"Optimized parameters gamma:\n",
" [3.14046713 0.73681226 4.99897226 0.46481489]\n",
"优化后的参数 beta:\n",
"Optimized parameters beta:\n",
" [0.82379898 2.50618308 4.85422542 1.90024859]\n"
]
}
......@@ -711,55 +493,59 @@
"paddle.seed(SEED)\n",
"\n",
"net = Net(p)\n",
"# 使用 Adam 优化器\n",
"# Use Adam optimizer\n",
"opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"# 梯度下降循环\n",
"# Gradient descent iteration\n",
"for itr in range(1, ITR + 1):\n",
" # 运行上面定义的网络\n",
" # Run the network defined above\n",
" loss, cir = net()\n",
" # 计算梯度并优化\n",
" loss.backward() \n",
" # Calculate the gradient and optimize\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" opt.clear_grad()\n",
" if itr % 10 == 0:\n",
" print(\"iter:\", itr, \" loss:\", \"%.4f\" % loss.numpy())\n",
" if itr% 10 == 0:\n",
" print(\"iter:\", itr, \"loss:\", \"%.4f\"% loss.numpy())\n",
" if itr == ITR:\n",
" print(\"\\nThe trained circuit:\") \n",
" print(cir)\n",
"\n",
"gamma_opt = net.gamma.numpy()\n",
"print(\"优化后的参数 gamma:\\n\", gamma_opt)\n",
"print(\"Optimized parameters gamma:\\n\", gamma_opt)\n",
"beta_opt = net.beta.numpy()\n",
"print(\"优化后的参数 beta:\\n\", beta_opt)"
"print(\"Optimized parameters beta:\\n\", beta_opt)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 解码量子答案\n",
"当求得损失函数的最小值以及相对应的一组参数 $\\vec{\\gamma}^*,\\vec{\\beta}^*$ 后,我们的任务还没有完成。为了进一步求得 Max-Cut 问题的近似解,需要从 QAOA 输出的量子态 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 中解码出经典优化问题的答案。物理上,解码量子态需要对量子态进行测量,然后统计测量结果的概率分布:\n",
"### Decoding the quantum solution\n",
"\n",
"After obtaining the minimum value of the loss function and the corresponding set of parameters $\\vec{\\gamma}^*,\\vec{\\beta}^*$, our task has not been completed. In order to obtain an approximate solution to the Max-Cut Problem, it is necessary to decode the solution to the classical optimization problem from the quantum state $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ output by QAOA. Physically, to decode a quantum state, we need to measure it and then calculate the probability distribution of the measurement results:\n",
"\n",
"$$\n",
"p(z)=|\\langle z|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle|^2.\n",
"\\tag{41}\n",
"\\tag{16}\n",
"$$\n",
"\n",
"通常情况下,某个比特串出现的概率越大,意味着其对应 Max-Cut 问题最优解的可能性越大。\n",
"Usually, the greater the probability of a certain bit string, the greater the probability that it corresponds to an optimal solution of the Max-Cut problem.\n",
"\n",
"Paddle Quantum 提供了查看 QAOA 量子电路输出状态的测量结果概率分布的函数:"
"Paddle Quantum provides a function to view the probability distribution of the measurement results of the state output by the QAOA quantum circuit:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 11,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:11:31.577428Z",
"start_time": "2021-02-22T11:11:31.390862Z"
"end_time": "2021-04-30T09:10:21.794006Z",
"start_time": "2021-04-30T09:10:21.392963Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -771,7 +557,7 @@
}
],
"source": [
"# 模拟重复测量电路输出态 1024 次\n",
"# Repeat the simulated measurement of the circuit output state 1024 times\n",
"prob_measure = cir.measure(plot=True)"
]
},
......@@ -779,21 +565,21 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"通过测量,找到出现几率最高的比特串。 此时,记其在该比特串中对应的比特取值为 $0$ 的顶点属于集合 $S_0$ 以及对应比特取值为 $1$ 的顶点属于集合 $S_1$,这两个顶点集合之间存在的边就是该图的一个可能的最大割方案。\n",
"After measurement, we can find the bit string with the highest probability of occurrence. Let the vertices whose bit values are $0$ in the bit string belong to the set $S_0$ and the vertices whose bit values are $1$ belong to the set $S_1$. The set of edges between these two vertex sets is a possible maximum cut of the graph.\n",
"\n",
"下面的代码选取测量结果中出现几率最大的比特串,然后将其映射回经典解,并且画出对应的最大割方案:\n",
"- 红色顶点属于集合 $S_0$,\n",
"- 蓝色顶点属于集合 $S_1$,\n",
"- 虚线表示被割的边。"
"The following code selects the bit string with the greatest chance of appearing in the measurement result, then maps it back to the classic solution, and draws the corresponding maximum cut:\n",
"- The red vertex belongs to the set $S_0$,\n",
"- The blue vertex belongs to the set $S_1$,\n",
"- The dashed line indicates the edge being cut."
]
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 12,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-22T11:11:34.819301Z",
"start_time": "2021-02-22T11:11:34.761119Z"
"end_time": "2021-04-30T09:10:36.652097Z",
"start_time": "2021-04-30T09:10:36.465888Z"
}
},
"outputs": [
......@@ -801,7 +587,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"找到的割的比特串形式: 1010\n"
"The bit string form of the cut found: 1010\n"
]
},
{
......@@ -816,11 +602,11 @@
}
],
"source": [
"# 找到测量结果中出现几率最大的比特串\n",
"# Find the most frequent bit string in the measurement results\n",
"cut_bitstring = max(prob_measure, key=prob_measure.get)\n",
"print(\"找到的割的比特串形式:\", cut_bitstring)\n",
"print(\"The bit string form of the cut found:\", cut_bitstring)\n",
"\n",
"# 在图上画出上面得到的比特串对应的割\n",
"# Draw the cut corresponding to the bit string obtained above on the graph\n",
"node_cut = [\"blue\" if cut_bitstring[v] == \"1\" else \"red\" for v in V]\n",
"\n",
"edge_cut = [\n",
......@@ -844,7 +630,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"可以看到,在这个例子中 QAOA 找到了图上的一个最大割。"
"As you can see, in this example, QAOA has found a maximum cut on the graph."
]
},
{
......@@ -853,13 +639,9 @@
"source": [
"_______\n",
"\n",
"## 参考文献\n",
"## References\n",
"\n",
"[1] Farhi, E., Goldstone, J. & Gutmann, S. A Quantum Approximate Optimization Algorithm. [arXiv:1411.4028 (2014).](https://arxiv.org/abs/1411.4028)\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",
"\n",
"[3] Duan, R. Quantum Adiabatic Theorem Revisited. [arXiv:2003.03063 (2020).](https://arxiv.org/abs/2003.03063)"
"[1] Farhi, E., Goldstone, J. & Gutmann, S. A Quantum Approximate Optimization Algorithm. [arXiv:1411.4028 (2014).](https://arxiv.org/abs/1411.4028)"
]
}
],
......@@ -879,7 +661,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......@@ -890,9 +672,14 @@
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_position": {
"height": "calc(100% - 180px)",
"left": "10px",
"top": "150px",
"width": "426.667px"
},
"toc_section_display": true,
"toc_window_display": true
"toc_window_display": false
},
"varInspector": {
"cols": {
......
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 量子近似优化算法\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 概览\n",
"\n",
"量子近似优化算法(quantum approximate optimization algorithm, QAOA)是可以在近期的有噪中等规模量子(noisy intermediate-scale quantum, NISQ)设备上运行且具有广泛应用前景的量子算法。QAOA 由 Edward Farhi 等人于 2014 年提出 [1],其目的是近似地求解组合优化问题(combinatorial optimization problems)。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 组合优化问题\n",
"\n",
"在应用数学和理论计算机科学的领域中,组合优化是在一个有限的对象集中找出最优对象的一类课题。简单来说,组合优化问题是指问题的所有解是由离散变量组成的,然后在离散的解集中寻找最优解。组合优化问题涉及的范围很广,且常见于实际生活中,例如飞机航线的设计、快递物流路线的规划等。\n",
"\n",
"具体来说,一个组合优化问题可以由 $n$ 个比特(bit)和 $m$ 个子句(clause)描述。每个比特是一个二进制变量,其取值为 $0$ 或 $1$,我们用 $z_j$ 表示第 $j$ 个比特的取值。因此,这 $n$ 个比特的取值可以由比特串 $z=z_1z_2\\dots z_n$ 表示。每个子句都是对部分比特的一个限制条件,例如一个子句可以要求第 $2$ 个比特的取值为 $0$,或者可以要求第 $3$ 个比特和第 $5$ 个比特的取值相同,等等。对于第 $j$ 个子句,我们定义一个与之相关的函数\n",
"\n",
"$$\n",
"C_j(z)=\n",
"\\begin{cases}\n",
"1 & \\text{如果 $n$ 个比特的取值 $z$ 满足子句 $j$ 表明的条件}\\\\\n",
"0 & \\text{如果 $n$ 个比特的取值 $z$ 不满足子句 $j$ 表明的条件}\n",
"\\end{cases}.\n",
"\\tag{1}\n",
"$$\n",
"\n",
"例如,如果第一个子句要求第二个比特的取值为 0,那么我们有 $C_1(z_10z_3\\dots z_n)=1$ 和 $C_1(z_11z_3\\dots z_n)=0$。\n",
"\n",
"由公式(1)中我们对于每个子句定义的函数 $C_j$,我们可以定义该组合优化问题的目标函数(objective function)\n",
"\n",
"$$\n",
"C(z)=\\sum_{j=1}^m w_jC_j(z),\n",
"\\tag{2}\n",
"$$\n",
"\n",
"其中 $w_j$ 是第 $j$ 个子句的权重(weight)。组合优化问题就是要找到一个取值 $z$ 使得目标函数 $C(z)$ 的值最大,即\n",
"\n",
"$$\n",
"\\underset{z}{\\operatorname{argmax}} C(z).\n",
"\\tag{3}\n",
"$$\n",
"\n",
"在理论计算机科学中,有一个著名的问题叫作布尔可满足性问题(Boolean satisfiability problem, SAT),它是指对于输入的一组 $n$ 个比特和 $m$ 个子句,判断是否存在一种 $n$ 个比特的取值同时满足所有 $m$ 个子句。而一个与之相关的优化问题叫作最大布尔可满足性问题(MAX-SAT),该问题是要寻找一种 $n$ 个比特的取值以同时满足尽可能多的子句。值得注意的是,上面定义组合优化问题的方式其实就是将其抽象为了 MAX-SAT,更准确地说,是 MAX-SAT 的一个推广版本,即加权 MAX-SAT(weighted MAX-SAT)。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 量子近似优化算法\n",
"\n",
"在实际生活中,许多组合优化问题都属于 NP 完全(NP-complete)问题甚至是 NP 困难(NP-hard)问题,这意味着计算机很可能无法高效地解决这样的问题。此时,一种替代方案便是寻找这类问题的近似最优解,而这样的任务通常是可以高效完成的。QAOA 就是一个可以寻找到一个组合优化问题的近似最优解的量子算法。\n",
"\n",
"### 编码组合优化问题\n",
"\n",
"对于上述的一个组合优化问题,有 $n$ 个比特和 $m$ 个子句。QAOA 算法将这个问题转化为了在 $n$ 个量子比特系统上的优化问题,该量子系统的每个计算基态 $|z\\rangle \\in \\{0,1\\}^n$ 对应着原问题中 $n$ 个比特的一种取值 $z$。同时,对于原问题中的第 $j$ 个子句,我们定义一个对角(diagonal)哈密顿量 $H_{C_j}$ 使其满足\n",
"\n",
"$$\n",
"H_{C_j}|z\\rangle = C_j(z)|z\\rangle.\n",
"\\tag{4}\n",
"$$\n",
"\n",
"具体我们可以通过下式来构造哈密顿量 $H_{C_j}$:\n",
"\n",
"$$\n",
"H_{C_j} = \\sum_{z\\in\\{0,1\\}^n} C_j(z)|z\\rangle\\langle z|.\n",
"\\tag{5}\n",
"$$\n",
"\n",
"例如,假设满足第 $j$ 个子句的取值有 $z^{(1)}$ 和 $z^{(2)}$,那么我们可以定义\n",
"\n",
"$$\n",
"H_{C_j} = |z^{(1)}\\rangle\\langle z^{(1)}| + |z^{(2)}\\rangle\\langle z^{(2)}|.\n",
"\\tag{6}\n",
"$$\n",
"\n",
"由此,QAOA 将组合优化问题的目标函数 $C$ 编码成了 $n$ 个量子比特系统上的哈密顿量\n",
"\n",
"$$\n",
"H_C = \\sum_{j=1}^m w_jH_{C_j},\n",
"\\tag{7}\n",
"$$\n",
"\n",
"并且\n",
"\n",
"$$\n",
"H_C|z\\rangle = \\sum_{j=1}^m w_jH_{C_j}|z\\rangle = \\sum_{j=1}^m w_jC_j(z)|z\\rangle = C(z)|z\\rangle.\n",
"\\tag{8}\n",
"$$\n",
"\n",
"值得注意的是,假设原问题的一个最优解是 $z_\\text{opt}$,那么我们有\n",
"\n",
"$$\n",
"\\langle z_\\text{opt}|H_C|z_\\text{opt}\\rangle = \\langle z_\\text{opt}|C(z_\\text{opt})|z_\\text{opt}\\rangle = C(z_\\text{opt})\\langle z_\\text{opt}|z_\\text{opt}\\rangle = C(z_\\text{opt}).\n",
"\\tag{9}\n",
"$$\n",
"\n",
"因此,原组合优化问题的最优解是哈密顿量 $H_C$ 的一个拥有最大本征值(eigenvalue)的本征态(eigenstate)。此外,对于任意量子态 $|\\psi\\rangle$,\n",
"\n",
"$$\n",
"\\langle\\psi|H_C|\\psi\\rangle \\leq C(z_\\text{opt}),\n",
"\\tag{10}\n",
"$$\n",
"\n",
"且该式取等号当且仅当 $|\\psi\\rangle$ 是几个最优解的叠加态。由式(9)和式(10)可以得到,\n",
"\n",
"$$\n",
"\\max_{|\\psi\\rangle} \\langle\\psi|H_C|\\psi\\rangle = C(z_\\text{opt}),\n",
"\\tag{11}\n",
"$$\n",
"\n",
"并且寻找原组合优化问题的最优解等同于寻找哈密顿量 $H_C$ 的一个拥有最大本征值的本征态,即寻找一个量子态 $|\\psi\\rangle$ 使得\n",
"\n",
"$$\n",
"H_C|\\psi\\rangle = C(z_\\text{opt})|\\psi\\rangle.\n",
"\\tag{12}\n",
"$$\n",
"\n",
"找到这样一个量子态 $|\\psi\\rangle$ 后,它很可能并不是一个计算基态,而是几个计算基态的叠加,这其中的每个计算基态都是原组合优化问题的一个最优解。因此,我们对 $|\\psi\\rangle$ 进行计算基上的测量,便能得到原组合优化问题的一个最优解。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 寻找近似最优解\n",
"\n",
"尽管将要解决的组合优化问题的目标函数编码成一个量子系统的哈密顿量 $H_C$ 较为简单,但想要根据式(11)从偌大的希尔伯特空间中找到代表最优解的量子态 $|\\psi\\rangle$ 并不容易。为了找到这样一个量子态,我们需要借助另一个哈密顿量\n",
"\n",
"$$\n",
"H_B = \\sum_{j=1}^n X_j,\n",
"\\tag{13}\n",
"$$\n",
"\n",
"其中 $X_j$ 表示作用在第 $j$ 个量子比特上的 Pauli $X$ 门。Pauli $X$ 门的两个本征态分别是 $|+\\rangle$ 和 $|-\\rangle$,它们对应的本征值分别是 $1$ 和 $-1$:\n",
"\n",
"$$\n",
"\\begin{align}\n",
"X|+\\rangle &=\n",
"\\begin{bmatrix}\n",
"0&1\\\\1&0\n",
"\\end{bmatrix}\n",
"\\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\1\n",
"\\end{bmatrix}\n",
"= \\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\1\n",
"\\end{bmatrix}\n",
"= |+\\rangle,\\tag{14}\\\\\n",
"X|-\\rangle &=\n",
"\\begin{bmatrix}\n",
"0&1\\\\1&0\n",
"\\end{bmatrix}\n",
"\\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\-1\n",
"\\end{bmatrix}\n",
"= \\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"-1\\\\1\n",
"\\end{bmatrix}\n",
"= -|-\\rangle.\\tag{15}\n",
"\\end{align}\n",
"$$\n",
"\n",
"因此,$H_B$ 的拥有最大本征值的本征态为\n",
"\n",
"$$\n",
"|s\\rangle \\equiv \\underbrace{|+\\rangle\\otimes\\cdots\\otimes|+\\rangle}_{\\text{共 $n$ 个 }|+\\rangle} = |+\\rangle^{\\otimes n}.\n",
"\\tag{16}\n",
"$$\n",
"\n",
"我们将把这个量子态 $|s\\rangle$ 作为算法的初始态。构造出哈密顿量 $H_C$ 和 $H_B$ 后,我们就可以开始寻找原组合优化问题的一个近似最优解了。根据哈密顿量 $H_C$ 和 $H_B$,分别定义酉变换\n",
"\n",
"$$\n",
"U_C(\\gamma) = e^{-i\\gamma H_C}\n",
"\\tag{17}\n",
"$$\n",
"\n",
"和酉变换\n",
"\n",
"$$\n",
"U_B(\\beta) = e^{-i\\beta H_B},\n",
"\\tag{18}\n",
"$$\n",
"\n",
"其中 $\\gamma$ 和 $\\beta$ 是实数,为可调节的参数。给定任意一个整数 $p\\geq1$ 以及参数 $\\vec{\\gamma}=(\\gamma_1,\\dots,\\gamma_p)$ 和 $\\vec{\\beta}=(\\beta_1,\\dots,\\beta_p)$,我们定义\n",
"\n",
"$$\n",
"|\\vec{\\gamma},\\vec{\\beta}\\rangle = U_B(\\beta_p)U_C(\\gamma_p)\\cdots U_B(\\beta_1)U_C(\\gamma_1)|s\\rangle.\n",
"\\tag{19}\n",
"$$\n",
"\n",
"可以看到,整数 $p$ 表示用到的 $U_C,U_B$ 的层数,即分别将 $U_C$ 和 $U_B$ 交替地作用在初始态 $|s\\rangle$ 上 $p$ 次。我们记 $F_p(\\vec{\\gamma},\\vec{\\beta})$ 为哈密顿量 $H_C$ 在式(19)的量子态下的期望值,\n",
"\n",
"$$\n",
"F_p(\\vec{\\gamma},\\vec{\\beta}) = \\langle\\vec{\\gamma},\\vec{\\beta}|H_C|\\vec{\\gamma},\\vec{\\beta}\\rangle.\n",
"\\tag{20}\n",
"$$\n",
"\n",
"通过调整参数 $\\vec{\\gamma},\\vec{\\beta}$,我们可以得到\n",
"\n",
"$$\n",
"M_p = \\max_{\\vec{\\gamma},\\vec{\\beta}} F_p(\\vec{\\gamma},\\vec{\\beta})\n",
"\\tag{21}\n",
"$$\n",
"\n",
"作为给定层数 $p$ 下的近似最优解。至此,我们将寻找量子态 $|\\psi\\rangle$ 的问题转变为了搜寻参数 $\\vec{\\gamma},\\vec{\\beta}$ 的问题。值得注意的是,$p$ 层酉变换 $U_C,U_B$ 的表达能力强于 $p-1$ 层的表达能力,因此\n",
"\n",
"$$\n",
"M_p \\geq M_{p-1}.\n",
"\\tag{22}\n",
"$$\n",
"\n",
"事实上,当 $p$ 足够大时,\n",
"\n",
"$$\n",
"\\lim_{p\\to\\infty} M_p = \\max_z C(z).\n",
"\\tag{23}\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 解码量子答案\n",
"\n",
"在上一段中,尽管我们将寻找量子态 $|\\psi\\rangle$ 转变为了寻找参数化量子态 $|\\vec{\\gamma},\\vec{\\beta}\\rangle$ 以方便我们的搜索,但同时我们也缩小了搜索的空间,也就是说,在给定层数 $p$ 的情况下,可能并不存在参数 $\\vec{\\gamma},\\vec{\\beta}$ 使得 $F_p(\\vec{\\gamma},\\vec{\\beta}) = C(z_\\text{opt})$。假设参数 $\\vec{\\gamma}^*$ 和 $\\vec{\\beta}^*$ 使得 $F_p$ 最大,即 $F_p(\\vec{\\gamma}^*,\\vec{\\beta}^*) = M_p$,那么在理想情况下量子态 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 包含了最优解的信息。但要注意的是,这里只使用了 $p$ 层,因此很可能 $M_p < C(z_\\text{opt})$。因此,一般情况下 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 只包含了近似最优解的信息。进一步地,我们假设量子态 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 是 $l$ 个计算基态的叠加态,即\n",
"\n",
"$$\n",
"|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle = c_1|z^{(1)}\\rangle + \\cdots + c_l|z^{(l)}\\rangle.\n",
"\\tag{24}\n",
"$$\n",
"\n",
"通常情况下,一个态 $|z^{(j)}\\rangle$ 在计算基上测量得到的概率 $|c_j|^2$ 越大,意味着其对应的比特串 $z^{(j)}$ 是最优解的可能性越大。那么我们制备 $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ 并测量,得到一个比特串 $z$ 并计算 $C(z)$ 的值。重复多次这个过程,便能得到一个 $z$ 使得 $C(z)$ 接近甚至超过 $M_p$。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 绝热定理\n",
"\n",
"为什么可以用上述的方法来构造量子态 $|\\vec{\\gamma},\\vec{\\beta}\\rangle$? QAOA 试图找到一个优化问题的近似最优解,一个与之类似的算法是量子绝热算法 [2](quantum adiabatic algorithm, QAA)。但不同的是,QAA 是为了找到优化问题的最优解而非近似最优解。与 QAOA 类似,QAA 将一个优化问题转化为了求一个哈密顿量的基态的问题,并利用绝热定理(adiabatic theorem)对其求解。考虑一个量子系统的哈密顿量\n",
"\n",
"$$\n",
"H(t) = (1-\\frac tT)H_B + \\frac tT H_C,\n",
"\\tag{25}\n",
"$$\n",
"\n",
"初始时,时间 $t=0$,该系统的哈密顿量为 $H(0) = H_B$。随着时间的流逝,该系统的哈密顿量逐渐由 $H_B$ 变为 $H_C$。当 $t=T$ 时,该系统的哈密顿量变为 $H(T) = H_C$。量子力学中的绝热定理告诉我们,如果初始时该系统处于 $H_B$ 的一个本征态,那么只要时间 $T$ 足够长,当系统的哈密顿量完全演化为 $H_C$ 时,该系统会处于 $H_C$ 的对应能级的本征态。因此,如果初始时该系统处于 $|s\\rangle$,即 $H_B$ 拥有最大本征值的本征态,经过足够长的演化时间 $T$,该系统的量子态会变为 $H_C$ 拥有最大本征值的本征态。[3]\n",
"\n",
"一种模拟哈密顿量 $H(t)$ 随着时间 $t$ 演化的方法便是交替地在该量子系统上作用酉变换 $U_C(\\gamma)$ 和 $U_B(\\beta)$,而模拟的精度取决于 $\\gamma,\\beta$ 的取值。另外,为了让系统的演化遵循绝热定理,需要足够长的演化时间,所以要求 $p$ 的取值足够大。因此,结合公式(22)可以推出公式(23)中的结论。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_______\n",
"\n",
"## 参考文献\n",
"\n",
"[1] Farhi, E., Goldstone, J. & Gutmann, S. A Quantum Approximate Optimization Algorithm. [arXiv:1411.4028 (2014).](https://arxiv.org/abs/1411.4028)\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",
"\n",
"[3] Duan, R. Quantum Adiabatic Theorem Revisited. [arXiv:2003.03063 (2020).](https://arxiv.org/abs/2003.03063)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"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_minor": 4
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-06T07:10:17.389768Z",
"start_time": "2021-01-06T07:10:17.379639Z"
}
},
"source": [
"# Quantum Approximate Optimization Algorithm\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"Quantum Approximate Optimization Algorithm (QAOA) is a quantum algorithm that can run on recent Noisy Intermediate-Scale Quantum (NISQ) devices and has a wide range of applications. QAOA was proposed by Edward Farhi et al. in 2014 [1], and its purpose is to solve combinatorial optimization problems approximately."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Combinatorial optimization problem\n",
"\n",
"In applied mathematics and theoretical computer science, combinatorial optimization is a type of topic that finds the optimal object in a discrete set of objects. In simple terms, the combinatorial optimization problem means that all solutions of the problem are composed of discrete variables, and the optimal solution is to be found in the discrete solution set. Combinatorial optimization problems involve a wide range of areas and are common in real life, such as the design of aircraft routes and the planning of express delivery routes.\n",
"\n",
"Specifically, a combinatorial optimization problem can be described by $n$ bits and $m$ clauses. Each bit is a binary variable whose value is $0$ or $1$, and we use $z_j$ to denote the value of the $j$th bit. Therefore, the value of these $n$ bits can be represented by the bit string $z=z_1z_2\\dots z_n$. Each clause is a restriction on some bits. For example, a clause can require the value of the $2$nd bit to be $0$, or it can require the value of the $3$rd bit and the $5$th bit to be the same. For the $j$th clause, we define a function\n",
"\n",
"$$\n",
"C_j(z)=\n",
"\\begin{cases}\n",
"1 & \\text{If the value $z$ of $n$ bits satisfies the condition indicated by clause $j$}\\\\\n",
"0 & \\text{if the value $z$ of $n$ bits does not satisfy the condition indicated by clause $j$}\n",
"\\end{cases}.\n",
"\\tag{1}\n",
"$$\n",
"\n",
"For example, if the first clause requires the value of the second bit to be 0, then we have $C_1(z_10z_3\\dots z_n)=1$ and $C_1(z_11z_3\\dots z_n)=0$.\n",
"\n",
"From the definition of $C_j$ in equation (1), we can define the objective function of the combinatorial optimization problem\n",
"\n",
"$$\n",
"C(z)=\\sum_{j=1}^m w_jC_j(z),\n",
"\\tag{2}\n",
"$$\n",
"\n",
"where $w_j$ is the weight of the $j$th clause. The combinatorial optimization problem is to find a value $z$ that maximizes the value of the objective function $C(z)$, namely\n",
"\n",
"$$\n",
"\\underset{z}{\\operatorname{argmax}} C(z).\n",
"\\tag{3}\n",
"$$\n",
"\n",
"In theoretical computer science, there is a famous problem called the Boolean satisfiability problem (SAT). This problem asks that, given $n$ bits and $m$ clauses as inputs, if there exists a value these bits can take so that all the $m$ clauses are satisfied simultaneously. An optimization problem related to SAT is MAX-SAT, which asks that what value these $n$ bits should take so that as many as possible clauses are satisfied. It is worth noting that the way we define a combinatorial optimization problem above is to formulate it as MAX-SAT, or more precisely, weighted MAX-SAT."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Quantum approximate optimization algorithm\n",
"\n",
"Many combinatorial optimization problems are NP-complete or even NP-hard problems, which means that computers may not be able to solve such problems efficiently. An alternative is to find the approximate optimal solution to such problems, and this task can usually be completed efficiently. QAOA is a quantum algorithm that can find an approximate optimal solution to a combinatorial optimization problem.\n",
"\n",
"### Encoding combinatorial optimization problem\n",
"\n",
"For the above combinatorial optimization problem, there are $n$ bits and $m$ clauses. The QAOA algorithm transforms this problem into an optimization problem on an $n$-qubit system. Each computational basis state $|z\\rangle \\in \\{0,1\\}^n$ of the quantum system corresponds to a value $z$ of $n$ bits in the original problem. At the same time, for the $j$th clause in the original problem, we define a diagonal Hamiltonian $H_{C_j}$ satisfying\n",
"\n",
"$$\n",
"H_{C_j}|z\\rangle = C_j(z)|z\\rangle.\n",
"\\tag{4}\n",
"$$\n",
"\n",
"Specifically, we can construct the Hamiltonian $H_{C_j}$ through the following equation:\n",
"\n",
"$$\n",
"H_{C_j} = \\sum_{z\\in\\{0,1\\}^n} C_j(z)|z\\rangle\\langle z|.\n",
"\\tag{5}\n",
"$$\n",
"\n",
"For example, assuming that $z^{(1)}$ and $z^{(2)}$ are the values ​​satisfying the $j$th clause, then we can define\n",
"\n",
"$$\n",
"H_{C_j} = |z^{(1)}\\rangle\\langle z^{(1)}| + |z^{(2)}\\rangle\\langle z^{(2)}|.\n",
"\\tag{6}\n",
"$$\n",
"\n",
"Therefore, QAOA encodes the objective function $C$ of the combinatorial optimization problem into the Hamiltonian $H_C$ on a system with $n$ qubits, where\n",
"\n",
"$$\n",
"H_C = \\sum_{j=1}^m w_jH_{C_j},\n",
"\\tag{7}\n",
"$$\n",
"\n",
"and\n",
"\n",
"$$\n",
"H_C|z\\rangle = \\sum_{j=1}^m w_jH_{C_j}|z\\rangle = \\sum_{j=1}^m w_jC_j(z)|z\\rangle = C(z)|z\\rangle .\n",
"\\tag{8}\n",
"$$\n",
"\n",
"It is worth noting that if an optimal solution to the original problem is $z_\\text{opt}$, then we have\n",
"\n",
"$$\n",
"\\langle z_\\text{opt}|H_C|z_\\text{opt}\\rangle = \\langle z_\\text{opt}|C(z_\\text{opt})|z_\\text{opt}\\rangle = C( z_\\text{opt})\\langle z_\\text{opt}|z_\\text{opt}\\rangle = C(z_\\text{opt}).\n",
"\\tag{9}\n",
"$$\n",
"\n",
"Therefore, an optimal solution of the original combinatorial optimization problem is an eigenstate with the largest eigenvalue of the Hamiltonian $H_C$. In addition, for any quantum state $|\\psi\\rangle$,\n",
"\n",
"$$\n",
"\\langle\\psi|H_C|\\psi\\rangle \\leq C(z_\\text{opt}),\n",
"\\tag{10}\n",
"$$\n",
"\n",
"and the equation takes the equal sign if and only if $|\\psi\\rangle$ is a superposition state of optimal solutions. It can be obtained from equation (9) and equation (10) that\n",
"\n",
"$$\n",
"\\max_{|\\psi\\rangle} \\langle\\psi|H_C|\\psi\\rangle = C(z_\\text{opt}),\n",
"\\tag{11}\n",
"$$\n",
"\n",
"and finding the optimal solution of the original combinatorial optimization problem is equivalent to finding an eigenstate with the largest eigenvalue of the Hamiltonian $H_C$, that is, finding a quantum state $|\\psi\\rangle$ such that\n",
"\n",
"$$\n",
"H_C|\\psi\\rangle = C(z_\\text{opt})|\\psi\\rangle.\n",
"\\tag{12}\n",
"$$\n",
"\n",
"When we find such a quantum state $|\\psi\\rangle$, it is probably not a computational basis state, but a superposition of several computational basis states, each of which is an optimal solution of the original combinatorial optimization problem. Therefore, we can obtain an optimal solution to the original combinatorial optimization problem by performing computational basis measurements on $|\\psi\\rangle$.\n",
"\n",
"### Finding an approximate optimal solution\n",
"\n",
"Although it is relatively simple to encode the objective function of the combinatorial optimization problem to be solved into the Hamiltonian $H_C$ of a quantum system, finding the quantum state $|\\psi\\rangle$ representing an optimal solution from the huge Hilbert space according to equation (11) is not easy. In order to find such a quantum state, we need another Hamiltonian\n",
"\n",
"$$\n",
"H_B = \\sum_{j=1}^n X_j,\n",
"\\tag{13}\n",
"$$\n",
"\n",
"where $X_j$ represents the Pauli $X$ gate acting on the $j$th qubit. The two eigenstates of Pauli $X$ gate are $|+\\rangle$ and $|-\\rangle$, and their corresponding eigenvalues ​​are $1$ and $-1$, respectively:\n",
"\n",
"$$\n",
"\\begin{align}\n",
"X|+\\rangle &=\n",
"\\begin{bmatrix}\n",
"0&1\\\\1&0\n",
"\\end{bmatrix}\n",
"\\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\1\n",
"\\end{bmatrix}\n",
"= \\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\1\n",
"\\end{bmatrix}\n",
"= |+\\rangle,\\tag{14}\\\\\n",
"X|-\\rangle &=\n",
"\\begin{bmatrix}\n",
"0&1\\\\1&0\n",
"\\end{bmatrix}\n",
"\\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"1\\\\-1\n",
"\\end{bmatrix}\n",
"= \\frac{1}{\\sqrt{2}}\n",
"\\begin{bmatrix}\n",
"-1\\\\1\n",
"\\end{bmatrix}\n",
"= -|-\\rangle.\\tag{15}\n",
"\\end{align}\n",
"$$\n",
"\n",
"Therefore, the eigenstate with the largest eigenvalue of $H_B$ is\n",
"\n",
"$$\n",
"|s\\rangle \\equiv \\underbrace{|+\\rangle\\otimes\\cdots\\otimes|+\\rangle}_\\text{$n$ terms} = |+\\rangle^{\\otimes n }.\n",
"\\tag{16}\n",
"$$\n",
"\n",
"We will use this quantum state $|s\\rangle$ as the initial state for the algorithm. After constructing the Hamiltonian $H_C$ and $H_B$, we can start to find an approximate optimal solution to the original combinatorial optimization problem. According to the Hamiltonian $H_C$ and $H_B$, respectively define the unitary transformation\n",
"\n",
"$$\n",
"U_C(\\gamma) = e^{-i\\gamma H_C}\n",
"\\tag{17}\n",
"$$\n",
"\n",
"and unitary transformation\n",
"\n",
"$$\n",
"U_B(\\beta) = e^{-i\\beta H_B},\n",
"\\tag{18}\n",
"$$\n",
"\n",
"where $\\gamma$ and $\\beta$ are adjustable real parameters. Given any integer $p\\geq1$ and the parameters $\\vec{\\gamma}=(\\gamma_1,\\dots,\\gamma_p)$ and $\\vec{\\beta}=(\\beta_1,\\dots,\\beta_p) $, we define\n",
"\n",
"$$\n",
"|\\vec{\\gamma},\\vec{\\beta}\\rangle = U_B(\\beta_p)U_C(\\gamma_p)\\cdots U_B(\\beta_1)U_C(\\gamma_1)|s\\rangle.\n",
"\\tag{19}\n",
"$$\n",
"\n",
"It can be seen that the integer $p$ represents the number of layers of $U_C, U_B$, that is, the $U_C$ and $U_B$ are alternately applied to the initial state $|s\\rangle$ $p$ times. Let us denote $F_p(\\vec{\\gamma},\\vec{\\beta})$ as the expected value of the Hamiltonian $H_C$ in the quantum state of equation (19):\n",
"\n",
"$$\n",
"F_p(\\vec{\\gamma},\\vec{\\beta}) = \\langle\\vec{\\gamma},\\vec{\\beta}|H_C|\\vec{\\gamma},\\vec{\\beta}\\rangle .\n",
"\\tag{20}\n",
"$$\n",
"\n",
"By adjusting the parameters $\\vec{\\gamma},\\vec{\\beta}$, we can get\n",
"\n",
"$$\n",
"M_p = \\max_{\\vec{\\gamma},\\vec{\\beta}} F_p(\\vec{\\gamma},\\vec{\\beta})\n",
"\\tag{21}\n",
"$$\n",
"\n",
"as the approximate optimal solution under a given number of layers $p$. So far, we have transformed the problem of searching for the quantum state $|\\psi\\rangle$ into a problem of searching for the parameters $\\vec{\\gamma},\\vec{\\beta}$. It is worth noting that the search space given by $p$ layers of $U_C, U_B$ is larger than that of $p-1$ layers, so\n",
"\n",
"$$\n",
"M_p \\geq M_{p-1}.\n",
"\\tag{22}\n",
"$$\n",
"\n",
"In fact, when $p$ is large enough,\n",
"\n",
"$$\n",
"\\lim_{p\\to\\infty} M_p = \\max_z C(z).\n",
"\\tag{23}\n",
"$$\n",
"\n",
"### Decoding the quantum solution\n",
"\n",
"In the previous paragraph, we simplify the search for the quantum state $|\\psi\\rangle$ into the search for the parameterized quantum state $|\\vec{\\gamma},\\vec{\\beta}\\rangle$, but at the same time, we have also reduced the search space. That is to say, given the number of layers $p$, there may be no parameters $\\vec{\\gamma},\\vec{\\beta}$ such that $F_p(\\vec{\\gamma},\\vec{\\beta}) = C(z_\\text{opt})$. Suppose that the parameters $\\vec{\\gamma}^*$ and $\\vec{\\beta}^*$ make $F_p$ the largest, that is, $F_p(\\vec{\\gamma}^*,\\vec{\\beta}^* ) = M_p$. Then under ideal circumstances, the quantum state $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ contains the information of an optimal solution. But it should be noted that only $p$ layers are used here, so it is very likely that $M_p < C(z_\\text{opt})$. Therefore, in general $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ only contains information about an approximate optimal solution. Furthermore, we assume that the quantum state $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ is the superposition state of $l$ computational basis state, namely\n",
"\n",
"$$\n",
"|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle = c_1|z^{(1)}\\rangle + \\cdots + c_l|z^{(l)}\\rangle.\n",
"\\tag{24}\n",
"$$\n",
"\n",
"Normally, the larger the probability $|c_j|^2$ that a state $|z^{(j)}\\rangle$ is measured on the computational basis, the more likely that the corresponding bit string $z^{(j) }$ is an optimal solution. Thus, we prepare $|\\vec{\\gamma}^*,\\vec{\\beta}^*\\rangle$ and measure it to get a bit string $z$ and calculate the value of $C(z)$. Repeat this process many times, and we can get a bit string $z$ that makes $C(z)$ close to or even exceed $M_p$.\n",
"\n",
"### Adiabatic theorem\n",
"\n",
"Why do we use the above method to construct the quantum state $|\\vec{\\gamma},\\vec{\\beta}\\rangle$? QAOA tries to find an approximate optimal solution to an optimization problem. A similar algorithm is the quantum adiabatic algorithm [2] (QAA). The difference is that QAA is designed to find an optimal solution to the optimization problem rather than an approximate one. Similar to QAOA, QAA transforms an optimization problem into a problem of finding the ground state of a Hamiltonian, and uses the adiabatic theorem to solve it. Consider the Hamiltonian\n",
"\n",
"$$\n",
"H(t) = (1-\\frac tT)H_B + \\frac tT H_C,\n",
"\\tag{25}\n",
"$$\n",
"\n",
"of a quantum system. At initial, time $t=0$, and the Hamiltonian of the system is $H(0) = H_B$. As time passes, the Hamiltonian of the system gradually changes from $H_B$ to $H_C$. When $t=T$, the Hamiltonian of the system becomes $H(T) = H_C$. The adiabatic theorem in quantum mechanics tells us that if the system is in an eigenstate of $H_B$ at the beginning, then as long as the evolution time $T$ is long enough, the system will be in the eigenstate of the corresponding energy level of $H_C$ when the Hamiltonian of the system completely evolves to $H_C$. Therefore, if the system is initially in $|s\\rangle$, that is, the eigenstate with the largest eigenvalue of $H_B$, after a sufficiently long evolution time $T$, the quantum state of the system will become the eigenstate with the largest eigenvalue of $H_C$. [3]\n",
"\n",
"One way to simulate the evolution of the Hamiltonian $H(t)$ over time $t$ is to alternately apply the unitary transformations $U_C(\\gamma)$ and $U_B(\\beta)$ on the quantum system, and the accuracy of simulation depends on the value of $\\gamma,\\beta$. In addition, in order for the evolution of the system to follow the adiabatic theorem, a sufficiently long evolution time is required, so the value of $p$ is required to be large enough. Therefore, combining equation (22) we can deduce the conclusion in equation (23)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_______\n",
"\n",
"## References\n",
"\n",
"[1] Farhi, E., Goldstone, J. & Gutmann, S. A Quantum Approximate Optimization Algorithm. [arXiv:1411.4028 (2014).](https://arxiv.org/abs/1411.4028)\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",
"\n",
"[3] Duan, R. Quantum Adiabatic Theorem Revisited. [arXiv:2003.03063 (2020).](https://arxiv.org/abs/2003.03063)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {
"height": "calc(100% - 180px)",
"left": "10px",
"top": "150px",
"width": "426.667px"
},
"toc_section_display": true,
"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_minor": 4
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 旅行商问题\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 概览\n",
"\n",
"旅行商问题(travelling salesman problem, TSP)是组合优化中最经典的 NP–困难的问题之一,它指的是以下这个问题:\"已知一系列的城市和它们之间的距离,这个旅行商想造访所有城市各一次,并最后返回出发地,求他的最短路线规划。\"\n",
"\n",
"这个问题也可以用图论的语言来描述。已知一个有权重的完全图 $G = (V,E)$。它的每个顶点 $i \\in V$ 都对应一个城市 $i$,并且每一条边 $(i,j) \\in E$ 的权重 $w_{i,j}$ 对应城市 $i$ 和城市 $j$ 的距离。需要注意的是,$G$ 是个无向图,所以权重是对称的,即 $w_{i,j}= w_{j,i}$。根据以上定义,旅行商问题可以转化为找这个图中最短的哈密顿回路(Hamiltonian cycle)的问题。哈密顿回路为一个通过且仅通过每一个顶点一次的回路。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 编码旅行商问题\n",
"\n",
"为了将旅行商问题转化成一个参数化量子电路(parameterized quantum circuits, PQC)可解的问题,我们首先需要编码旅行商问题的哈密顿量。我们先将此问题转化为一个整数规划问题:假设图形 $G$ 的顶点数量为 $|V| = n$ 个,那么对于每个顶点 $i \\in V$,我们定义 $n$ 个二进制变量 $x_{i,t}$,$t \\in [0,n-1]$:\n",
"\n",
"$$\n",
"x_{i, t}=\n",
"\\begin{cases}\n",
"1, & \\text{如果在最后的哈密顿回路中,顶点 } i \\text { 的顺序为 $t$,即在时间 $t$ 的时候被旅行商访问}\\\\\n",
"0, & \\text{其他情况}\n",
"\\end{cases}.\n",
"\\tag{1}\n",
"$$\n",
"\n",
"因为 $G$ 有 $n$ 个顶点,所以我们共有 $n^2$ 个变量 $x_{i,t}$,所有这些变量的取值我们用 $x=x_{1,1}x_{1,2}\\dots x_{n,n}$ 来表示。现在我们假设 $x$ 对应了一条哈密顿回路,那么对于图中的每一条边 $(i,j,w_{i,j}) \\in E$,条件 $x_{i,t} = x_{j,t+1} = 1$(也可以等价地写成 $x_{i,t}\\cdot x_{j,t+1} = 1$)成立当且仅当该哈密顿回路中的第 $t$ 个顶点是顶点 $i$ 并且第 $t+1$ 个顶点是顶点 $j$;否则,$x_{i,t}\\cdot x_{j,t+1} = 0$。所以我们可以用下式计算哈密顿回路的长度\n",
"\n",
"$$\n",
"D(x) = \\sum_{i,j} w_{i,j} \\sum_{t} x_{i,t} x_{j,t+1}.\n",
"\\tag{2}\n",
"$$\n",
"\n",
"根据哈密顿回路的定义,$x$ 如果对应一条哈密顿回路需要满足如下的限制:\n",
"\n",
"$$\n",
"\\sum_t x_{i,t} = 1 \\quad \\forall i \\in [0,n-1] \\quad \\text{ 和 } \\quad \\sum_i x_{i,t} = 1 \\quad \\forall t \\in [0,n-1],\n",
"\\tag{3}\n",
"$$\n",
"\n",
"其中第一个式子用来保证找到的 $x$ 所代表的路线中每个顶点仅出现一次,第二个式子保证在每个时间只有一个顶点可以出现。这两个式子共同保证了参数化量子电路找到的 $x$ 是个哈密顿回路。所以,我们可以定义在此限制下的代价函数:\n",
"\n",
"$$\n",
"C(x) = D(x)+ A\\left( \\sum_{i} \\left(1-\\sum_t x_{i,t}\\right)^2 + \\sum_{t} \\left(1-\\sum_i x_{i,t}\\right)^2 \\right).\n",
"\\tag{4}\n",
"$$\n",
"\n",
"其中 $A$ 是惩罚参数,它保证了上述的限制被遵守。因为我们想要在找哈密顿回路的长度 $D(x)$ 的最小值的同时保证 $x$ 确实表示一个哈密顿回路,所以我们需要设置一个大一点的 $A$,最起码大过图 $G$ 中边的最大的权重,从而保证不遵守限制的路线不会成为最终的路线。\n",
"\n",
"我们现在需要将代价函数 $C(x)$ 转化为一个哈密顿量从而完成旅行商问题的编码。每一个二进制变量可以取0和1两个值,分别对应量子态 $|0\\rangle$ 和 $|1\\rangle$。**每个二进制变量都对应一个量子比特,所以我们需要 $n^2$ 个量子比特来解决旅行商问题。** 和最大割问题相似,因为泡利 $Z$ 的两个本征态和我们需要的量子态 $|0\\rangle$、$|1\\rangle$ 一样,这两个本征态所对应的本征值分别是 1 和 -1,所以我们考虑利用泡利 $Z$ 矩阵将代价函数编码为哈密顿量。\n",
"\n",
"我们现在将二进制变量映射到泡利 $Z$ 矩阵上,从而使 $C(x)$ 转化成哈密顿矩阵:\n",
"\n",
"$$\n",
"x_{i,t} \\mapsto \\frac{I-Z_{i,t}}{2}, \\tag{5}\n",
"$$\n",
"\n",
"这里 $Z_{i,t} = I \\otimes I \\otimes \\ldots \\otimes Z \\otimes \\ldots \\otimes I$,也就是说 $Z$ 作用在位置在 $(i,t)$ 的量子比特上。通过这个映射,如果一个编号为 $(i,t)$ 的量子比特的量子态为 $|1\\rangle$,那么对应的二进制变量的取值为 $x_{i,t} = \\frac{I-Z_{i,t}}{2} |1\\rangle = 1$,也就是说顶点 $i$ 在最短哈密顿回路中的位置是 $t$。同样地,对于量子态为 $|0\\rangle$的量子比特 $(i,t)$,它所对应的二进制变量的取值为 $x_{i,t} = \\frac{I-Z_{i,t}}{2} |1\\rangle = 0$。\n",
"\n",
"我们用上述映射将 $C(x)$ 转化成量子比特数为 $n^2$ 的系统的哈密顿矩阵 $H_C$,从而实现了旅行商问题的量子化。这个哈密顿矩阵 $H_C$ 的基态即为旅行商问题的最优解。在接下来的章节中,我们将展示怎么用参数化量子电路找到这个矩阵的基态,即对应最小本征值的本征态。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Paddle Quantum 实现\n",
"\n",
"要在量桨上实现用参数化量子电路解决旅行商问题,首先要做的便是加载需要用到的包。其中 `networkx` 包可以帮助我们方便地处理图。"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:00:15.901429Z",
"start_time": "2021-05-17T08:00:12.708945Z"
}
},
"outputs": [],
"source": [
"# 加载量桨、飞桨的相关模块\n",
"import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.QAOA.tsp import tsp_hamiltonian # 构造旅行商问题哈密顿量的函数\n",
"from paddle_quantum.QAOA.tsp import solve_tsp_brute_force\n",
"\n",
"# 加载额外需要用到的包\n",
"from numpy import pi as PI\n",
"import matplotlib.pyplot as plt\n",
"import networkx as nx\n",
"import random"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"接下来,我们生成该旅行商问题中的图 $G$。为了运算方便,图中的顶点从0开始计数。"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:00:16.212260Z",
"start_time": "2021-05-17T08:00:15.918792Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# n 代表图形 G 的顶点数量\n",
"n = 4\n",
"E = [(0, 1, 3), (0, 2, 2), (0, 3, 10), (1, 2, 6), (1, 3, 2), (2, 3, 6)]\n",
"G = nx.Graph()\n",
"G.add_weighted_edges_from(E)\n",
"\n",
"# 将生成的图 G 打印出来\n",
"pos = nx.spring_layout(G)\n",
"options = {\n",
" \"with_labels\": True,\n",
" \"font_weight\": \"bold\",\n",
" \"font_color\": \"white\",\n",
" \"node_size\": 2000,\n",
" \"width\": 2\n",
"}\n",
"nx.draw_networkx(G, pos, **options)\n",
"nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=nx.get_edge_attributes(G,'weight'))\n",
"ax = plt.gca()\n",
"ax.margins(0.20)\n",
"plt.axis(\"off\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 编码哈密顿量\n",
"\n",
"量桨中,哈密顿量可以以 ``list`` 的形式输入。这里我们将式(4)中的二进制变量用式(5)替换,从而构建哈密顿量 $H_C$。\n",
"\n",
"为了节省量子比特数,我们改进了上述哈密顿量的构造:因为哈密顿回路的性质,顶点 $n-1$ 一定会被包括在其中,同时因为顶点的绝对顺序并不重要,所以我们可以**固定顶点 $n-1$ 在最短哈密顿回路的最后一个,即它所代表的城市最后一个被旅行商到访。** 这也就是说,对所有的 $t$ 和所有的 $i$,我们固定 $x_{n-1,t} = \\delta_{n-1,t}$ 和 $x_{i,n-1} = \\delta_{i,n-1}$(如果 $i=j$,那么$\\delta_{i,j} = 1$,反之则为 $0$)。\n",
"\n",
"这种改进将解决旅行商问题所需要的量子比特数从 $n^2$ 降到了 $(n-1)^2$,在我们接下来的实现当中都会使用改进过的哈密顿量来计算。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:00:16.237497Z",
"start_time": "2021-05-17T08:00:16.219567Z"
}
},
"outputs": [],
"source": [
"# 以 list 的形式构建哈密顿量 H_C\n",
"A = 20 # 惩罚参数\n",
"H_C_list = tsp_hamiltonian(G, A, n)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 计算损失函数\n",
"\n",
"在最大割问题([Max-Cut 教程](./MAXCUT_CN.ipynb))中,我们用 QAOA 构建了我们的参数化量子电路,但除了 QAOA 电路,其他的电路也可以用来解决组合优化问题。对于旅行商问题,我们将使用 $U_3(\\vec{\\theta})$ 和 $\\text{CNOT}$ 门构造的参数化量子电路。这可以通过调用量桨内部的 [`complex entangled layer`](https://qml.baidu.com/api/paddle_quantum.circuit.uansatz.html) 来实现。\n",
"\n",
"上述电路会给出一个输出态 $|\\vec{\\theta}\\rangle$,由此输出态,我们可以计算最大割问题的目标函数,也就是旅行商问题的损失函数:\n",
"\n",
"$$\n",
"L(\\vec{\\theta}) = \\langle\\vec{\\theta}|H_C|\\vec{\\theta}\\rangle.\n",
"\\tag{6}\n",
"$$\n",
"\n",
"然后我们利用经典的优化算法寻找最优参数 $\\vec{\\theta}^*$。下面的代码给出了通过量桨和飞桨搭建的完整网络:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:00:16.258893Z",
"start_time": "2021-05-17T08:00:16.241066Z"
}
},
"outputs": [],
"source": [
"class Net(paddle.nn.Layer):\n",
" def __init__(self, g, p, H_ls, dtype=\"float64\",):\n",
" super(Net, self).__init__()\n",
" self.p = p\n",
" self.theta = self.create_parameter(shape=[self.p, (len(g.nodes) - 1) ** 2, 3],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI),\n",
" dtype=dtype, is_bias=False)\n",
" self.H_ls = H_ls\n",
" self.num_qubits = (len(g) - 1) ** 2\n",
"\n",
" def forward(self):\n",
" # 定义 complex entangled layer\n",
" cir = UAnsatz(self.num_qubits)\n",
" cir.complex_entangled_layer(self.theta, self.p)\n",
" # 运行该量子电路\n",
" cir.run_state_vector()\n",
" # 计算损失函数\n",
" loss = cir.expecval(self.H_ls)\n",
"\n",
" return loss, cir"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 训练量子神经网络\n",
"\n",
"定义好了量子神经网络后,我们使用梯度下降的方法来更新其中的参数,使得式(6)的期望值最小。"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:00:16.274144Z",
"start_time": "2021-05-17T08:00:16.264684Z"
}
},
"outputs": [],
"source": [
"p = 2 # 量子电路的层数\n",
"ITR = 120 # 训练迭代的次数\n",
"LR = 0.5 # 基于梯度下降的优化方法的学习率\n",
"SEED = 1000 #设置随机数种子"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"这里,我们在飞桨中优化上面定义的网络。"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:02:14.495970Z",
"start_time": "2021-05-17T08:00:16.496407Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"循环数: 10 损失: 46.0238\n",
"循环数: 20 损失: 22.6651\n",
"循环数: 30 损失: 16.6195\n",
"循环数: 40 损失: 14.3719\n",
"循环数: 50 损失: 13.5548\n",
"循环数: 60 损失: 13.1736\n",
"循环数: 70 损失: 13.0661\n",
"循环数: 80 损失: 13.0219\n",
"循环数: 90 损失: 13.0035\n",
"循环数: 100 损失: 13.0032\n",
"循环数: 110 损失: 13.0008\n",
"循环数: 120 损失: 13.0004\n"
]
}
],
"source": [
"# 固定 paddle 随机种子\n",
"paddle.seed(SEED)\n",
"\n",
"net = Net(G, p, H_C_list)\n",
"# 使用 Adam 优化器\n",
"opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"# 梯度下降循环\n",
"for itr in range(1, ITR + 1):\n",
" # 运行上面定义的网络\n",
" loss, cir = net()\n",
" # 计算梯度并优化\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" opt.clear_grad()\n",
" if itr % 10 == 0:\n",
" print(\"循环数:\", itr, \"损失:\", \"%.4f\"% loss.numpy())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"最理想的情况是我们使用的量子神经网络可以找到最短哈密顿回路,同时最后的损失值应该等于这条回路上的权重之和,即旅行商所需要走的最短长度。但如果最后的情况不是这样,读者可以通过调整参数化量子电路的参数值,即 $p$,ITR 和 LR,来获得更好的训练效果。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 解码量子答案\n",
"\n",
"当求得损失函数的最小值以及相对应的一组参数 $\\vec{\\theta}^*$后,我们的任务还没有完成。为了进一步求得旅行商问题的近似解,需要从电路输出的量子态 $|\\vec{\\theta}^*\\rangle$ 中解码出经典优化问题的答案。物理上,解码量子态需要对量子态进行测量,然后统计测量结果的概率分布(我们的测量结果是表示旅行商问题答案的比特串):\n",
"\n",
"$$\n",
"p(z) = |\\langle z|\\vec{\\theta}^*\\rangle|^2.\n",
"\\tag{7}\n",
"$$\n",
"\n",
"通常情况下,某个比特串出现的概率越大,意味着其对应旅行商问题最优解的可能性越大。\n",
"\n",
"量桨提供了查看参数化量子电路输出状态的测量结果概率分布的函数:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:02:14.554317Z",
"start_time": "2021-05-17T08:02:14.500593Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"利用改进后的哈密顿量找到的解的比特串形式: 010001100\n"
]
}
],
"source": [
"# 模拟重复测量电路输出态 1024 次\n",
"prob_measure = cir.measure(shots=1024)\n",
"reduced_salesman_walk = max(prob_measure, key=prob_measure.get)\n",
"print(\"利用改进后的哈密顿量找到的解的比特串形式:\", reduced_salesman_walk)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"因为我们之前为了减少所需要的量子比特数改进了一下旅行商问题对应的哈密顿量,上面显示的比特串缺少了顶点 $n-1$ 的信息,以及所有顶点在时间 $t =n-1$ 的时候的信息。所以我们需要将这些信息加回找到的比特串中。\n",
"\n",
"首先为了加上对于 $i \\in [0,n-2]$, $x_{i,n-1} = 0$ 这一信息,我们需要在每 $(n-1)$ 个比特之后加上一个 $0$。接着在比特串的最后,我们为了加上顶点 $n-1$在每个时间的状态,我们加上包含 $n-1$ 个 '0' 的 '00...01',用来表示对于$t \\in [0,n-2]$来说,$x_{n-1,t} = 0$,同时 $x_{n-1,n-1} = 0$。\n",
"\n",
"以下代码通过测量,找到了出现几率最高的比特串,每一个比特都包含了式(1)定义的 $x_{i,t}$ 的信息。我们将找到的比特串映射回经典解,即转化成了 ``dictionary`` 的形式。其中 ``key`` 代表顶点编号,``value`` 代表顶点在哈密顿回路中的顺序,即访问城市的顺序。在以下代码中,我们还将量子电路找到的最优解和暴力算法找到的相比较,从而说明量子算法的正确性。"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:02:14.571954Z",
"start_time": "2021-05-17T08:02:14.559634Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"参数化量子电路找到的最优解: {0: 1, 1: 2, 2: 0, 3: 3} ,最短距离为: 13\n",
"经典暴力算法找到的最优解: {0: 0, 1: 1, 2: 3, 3: 2} ,最短距离为: 13\n"
]
}
],
"source": [
"# 参数化量子电路找到的最优解\n",
"str_by_vertex = [reduced_salesman_walk[i:i + n - 1] for i in range(0, len(reduced_salesman_walk) + 1, n - 1)]\n",
"salesman_walk = '0'.join(str_by_vertex) + '0' * (n - 1) + '1'\n",
"solution = {i:t for i in range(n) for t in range(n) if salesman_walk[i * n + t] == '1'}\n",
"distance = sum([G[u][v][\"weight\"] if solution[u] == (solution[v] + 1) % n \n",
" or solution[v] == (solution[u] + 1) % n else 0\n",
" for (u, v) in G.edges])\n",
"print(\"参数化量子电路找到的最优解:\", solution, \",最短距离为:\", distance)\n",
"\n",
"# 经典暴力算法找到的最优解\n",
"salesman_walk_brute_force, distance_brute_force = solve_tsp_brute_force(G)\n",
"solution_brute_force = {i:salesman_walk_brute_force.index(i) for i in range(n)}\n",
"print(\"经典暴力算法找到的最优解:\", solution_brute_force, \",最短距离为:\", distance_brute_force)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"以下的代码将字典形式的经典解用图的形式展示了出来:\n",
"* 顶点中的第一个数字代表城市编号\n",
"* 顶点中的第二个数字代表旅行商访问此城市的顺序\n",
"* 红色的边表示找到的最佳路线"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:02:14.864346Z",
"start_time": "2021-05-17T08:02:14.576418Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 1080x288 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"label_dict = {i: str(i) + \", \" + str(t) for i, t in solution.items()}\n",
"edge_color = [\"red\" if solution[u] == (solution[v] + 1) % n\n",
" or solution[v] == (solution[u] + 1) % n else \"black\"\n",
" for (u, v) in G.edges]\n",
"label_dict_bf = {i: str(i) + \", \" + str(t) for i, t in solution_brute_force.items()}\n",
"edge_color_bf = [\"red\" if solution_brute_force[u] == (solution_brute_force[v] + 1) % n\n",
" or solution_brute_force[v] == (solution_brute_force[u] + 1) % n else \"black\"\n",
" for (u, v) in G.edges]\n",
"\n",
"# 在图上画出上面得到的最优路线\n",
"fig, ax = plt.subplots(1, 2, figsize=(15, 4))\n",
"for i, a in enumerate(ax):\n",
" a.axis('off')\n",
" a.margins(0.20)\n",
"nx.draw(G, pos=pos, labels=label_dict, edge_color=edge_color, ax=ax[0], **options)\n",
"nx.drawing.nx_pylab.draw_networkx_edge_labels(G, pos=pos, ax=ax[0], edge_labels=nx.get_edge_attributes(G, 'weight'))\n",
"nx.draw(G, pos=pos, labels=label_dict_bf, edge_color=edge_color_bf, ax=ax[1], **options)\n",
"nx.drawing.nx_pylab.draw_networkx_edge_labels(G, pos=pos, ax=ax[1], edge_labels=nx.get_edge_attributes(G, 'weight'))\n",
"plt.axis(\"off\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"上面给出的左图展示了参数化量子电路找到的旅行商问题的最优解,右图展示了经典暴力算法找到的最优解。我们不难看出,即使旅行商访问每个城市的绝对顺序不一样,但路线是一致的,即相对顺序一样。这说明在这个例子中,参数化量子电路找到了旅行商问题的最优解。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 实际应用\n",
"\n",
"旅行商问题可以直接应用在很多交通和物流规划中,例如规划校车接送学生的路线。管理科学领域的先锋 Merrill Flood 在上世纪40年代就受到校车问题的启发,展开了对于旅行商问题的早期研究。更多近期的应用包括了路线规划 [1] 和电线公司对于电力传输的规划 [2]。\n",
"\n",
"除了交通运输问题,旅行商问题同样在管理问题中有很广泛的应用,比如计划机器在电路板上钻孔的顺序 [3]、重构 DNA 上的不明片段 [4] 以及规划最佳建筑路线 [5]。 一些咨询公司,比如 [Nexus](https://nexustech.com.ph/company/newsletter/article/Finding-the-shortest-path-Optimizing-food-trips) 也通过旅行商问题给外界提供管理咨询服务。\n",
"\n",
"同时作为最著名的组合优化问题之一,旅行商问题为很多用于解决组合问题的通用算法提供了测试平台。它经常被作为研究者测试他们提出的新的算法的首选例子。\n",
"\n",
"对于旅行商问题更多的应用和解法,详见 [6]。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_______\n",
"\n",
"## 参考文献\n",
"\n",
"[1] Bräysy, Olli, et al. \"An optimization approach for communal home meal delivery service: A case study.\" [Journal of Computational and Applied Mathematics 232.1 (2009): 46-53.](https://www.sciencedirect.com/science/article/pii/S0377042708005438)\n",
"\n",
"[2] Sloane, Thomas H., Frank Mann, and H. Kaveh. \"Powering the last mile: an alternative to powering FITL.\" [Proceedings of Power and Energy Systems in Converging Markets. IEEE, 1997.](https://ieeexplore.ieee.org/document/646046)\n",
"\n",
"[3] Onwubolu, Godfrey C. \"Optimizing CNC drilling machine operations: traveling salesman problem-differential evolution approach.\" [New optimization techniques in engineering. Springer, Berlin, Heidelberg, 2004. 537-565.](https://link.springer.com/chapter/10.1007/978-3-540-39930-8_22)\n",
"\n",
"[4] Caserta, Marco, and Stefan Voß. \"A hybrid algorithm for the DNA sequencing problem.\" [Discrete Applied Mathematics 163 (2014): 87-99.](https://www.sciencedirect.com/science/article/pii/S0166218X12003253)\n",
"\n",
"[5] Klanšek, Uroš. \"Using the TSP solution for optimal route scheduling in construction management.\" [Organization, technology & management in construction: an international journal 3.1 (2011): 243-249.](https://www.semanticscholar.org/paper/Using-the-TSP-Solution-for-Optimal-Route-Scheduling-Klansek/3d809f185c03a8e776ac07473c76e9d77654c389)\n",
"\n",
"[6] Matai, Rajesh, Surya Prakash Singh, and Murari Lal Mittal. \"Traveling salesman problem: an overview of applications, formulations, and solution approaches.\" [Traveling salesman problem, theory and applications 1 (2010).](https://www.sciencedirect.com/topics/computer-science/traveling-salesman-problem)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Travelling Salesman Problem\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"One of the most famous NP-hard problems in combinatorial optimization, the travelling salesman problem (TSP) considers the following question: \"Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city exactly once and returns to the origin city?\" \n",
"\n",
"This question can also be formulated in the language of graph theory. Given a weighted undirected complete graph $G = (V,E)$, where each vertex $i \\in V$ corresponds to city $i$ and the weight $w_{i,j}$ of each edge $(i,j,w_{i,j}) \\in E$ represents the distance between cities $i$ and $j$, the TSP is to find the shortest Hamiltonian cycle in $G$, where a Hamiltonian cycle is a closed loop on a graph in which every vertex is visited exactly once. Note that because $G$ is an undirected graph, weights are symmetric, i.e., $w_{i,j} = w_{j,i}$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Encoding the TSP\n",
"\n",
"To transform the TSP into a problem applicable for parameterized quantum circuits, we need to encode the TSP into a Hamiltonian. We realize the encoding by first constructing an integer programming problem. Suppose there are $n=|V|$ vertices in graph $G$. Then for each vertex $i \\in V$, we define $n$ binary variables $x_{i,t}$, where $t \\in [0,n-1]$, such that\n",
"\n",
"$$\n",
"x_{i, t}=\n",
"\\begin{cases}\n",
"1, & \\text {if in the resulting Hamiltonian cycle, vertex } i \\text { is visited at time } t\\\\\n",
"0, & \\text{otherwise}\n",
"\\end{cases}.\n",
"\\tag{1}\n",
"$$\n",
"\n",
"As there are $n$ vertices, we have $n^2$ variables in total, whose value we denote by a bit string $x=x_{1,1}x_{1,2}\\dots x_{n,n}$. Assume for now that the bit string $x$ represents a Hamiltonian cycle. Then for each edge $(i,j,w_{i,j}) \\in E$, we will have $x_{i,t} = x_{j,t+1}=1$, i.e., $x_{i,t}\\cdot x_{j,t+1}=1$, if and only if the Hamiltonian cycle visits vertex $i$ at time $t$ and vertex $j$ at time $t+1$; otherwise, $x_{i,t}\\cdot x_{j,t+1}$ will be $0$. Therefore the length of a Hamiltonian cycle is\n",
"\n",
"$$\n",
"D(x) = \\sum_{i,j} w_{i,j} \\sum_{t} x_{i,t} x_{j,t+1}.\n",
"\\tag{2}\n",
"$$\n",
"\n",
"For $x$ to represent a valid Hamiltonian cycle, the following constraint needs to be met:\n",
"\n",
"$$\n",
"\\sum_t x_{i,t} = 1 \\quad \\forall i \\in [0,n-1] \\quad \\text{ and } \\quad \\sum_i x_{i,t} = 1 \\quad \\forall t \\in [0,n-1],\n",
"\\tag{3}\n",
"$$\n",
"\n",
"where the first equation guarantees that each vertex is only visited once and the second guarantees that only one vertex is visited at each time $t$. Then the cost function under the constraint can be formulated below, with $A$ being the penalty parameter set to ensure that the constraint is satisfied:\n",
"\n",
"$$\n",
"C(x) = D(x)+ A\\left( \\sum_{i} \\left(1-\\sum_t x_{i,t}\\right)^2 + \\sum_{t} \\left(1-\\sum_i x_{i,t}\\right)^2 \\right).\n",
"\\tag{4}\n",
"$$\n",
"\n",
"Note that as we would like to minimize the length $D(x)$ while ensuring $x$ represents a valid Hamiltonian cycle, we had better set $A$ large, at least larger than the largest weight of edges.\n",
"\n",
"We now need to transform the cost function $C(x)$ into a Hamiltonian to realize the encoding of the TSP. Each variable $x_{i,j}$ has two possible values, $0$ and $1$, corresponding to quantum states $|0\\rangle$ and $|1\\rangle$. **Note that every variable corresponds to a qubit and so $n^2$ qubits are needed for solving the TSP.** Similar as in the Max-Cut problem, we consider the Pauli $Z$ operator as it has two eigenstates, $|0\\rangle$ and $|1\\rangle$. Their corresponding eigenvalues are 1 and -1, respectively.\n",
"\n",
"Now we would like to consider the mapping\n",
"\n",
"$$\n",
"x_{i,t} \\mapsto \\frac{I-Z_{i,t}}{2}, \\tag{5}\n",
"$$\n",
"\n",
"where $Z_{i,t} = I \\otimes I \\otimes \\ldots \\otimes Z \\otimes \\ldots \\otimes I$ with $Z$ operates on the qubit at position $(i,t)$. Under this mapping, if a qubit $(i,t)$ is in state $|1\\rangle$, then $x_{i,t} = \\frac{I-Z_{i,t}}{2} |1\\rangle = 1$, which means vertex $i$ is visited at time $t$. Also, for a qubit $(i,t)$ in state $|0\\rangle$, $x_{i,t} = \\frac{I-Z_{i,t}}{2} |1\\rangle = 0$.\n",
"\n",
"Thus using the above mapping, we can transform the cost function $C(x)$ into a Hamiltonian $H_C$ for the system of $n^2$ qubits and realize the quantumization of the TSP. Then the ground state of $H_C$ is the optimal solution to the TSP. In the following section, we will show how to use a parametrized quantum circuit to find the ground state, i.e., the eigenvector with the smallest eigenvalue.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Paddle Quantum Implementation\n",
"\n",
"To investigate the TSP using Paddle Quantum, there are some required packages to import, which are shown below. The ``networkx`` package is the tool to handle graphs."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:24:17.197426Z",
"start_time": "2021-05-17T08:24:12.896488Z"
}
},
"outputs": [],
"source": [
"# Import related modules from Paddle Quantum and PaddlePaddle\n",
"import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum.QAOA.tsp import tsp_hamiltonian\n",
"from paddle_quantum.QAOA.tsp import solve_tsp_brute_force\n",
"\n",
"# Import additional packages needed\n",
"from numpy import pi as PI\n",
"import matplotlib.pyplot as plt\n",
"import networkx as nx\n",
"import random"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we generate a weighted complete graph $G$ with four vertices. For the convenience of computation, the vertices here are labeled starting from $0$."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:24:24.302458Z",
"start_time": "2021-05-17T08:24:24.060967Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# n is the number of vertices in the graph G\n",
"n = 4\n",
"E = [(0, 1, 3), (0, 2, 2), (0, 3, 10), (1, 2, 6), (1, 3, 2), (2, 3, 6)]\n",
"G = nx.Graph()\n",
"G.add_weighted_edges_from(E)\n",
"\n",
"# Print out the generated graph G\n",
"pos = nx.spring_layout(G)\n",
"options = {\n",
" \"with_labels\": True,\n",
" \"font_weight\": \"bold\",\n",
" \"font_color\": \"white\",\n",
" \"node_size\": 2000,\n",
" \"width\": 2\n",
"}\n",
"nx.draw_networkx(G, pos, **options)\n",
"nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=nx.get_edge_attributes(G,'weight'))\n",
"ax = plt.gca()\n",
"ax.margins(0.20)\n",
"plt.axis(\"off\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Encoding Hamiltonian\n",
"\n",
"In Paddle Quantum, a Hamiltonian can be input in the form of ``list``. Here we construct the Hamiltonian $H_C$ of Eq. (4) with the replacement in Eq. (5). \n",
"\n",
"To save the number of qubits needed, we observe the following fact: it is clear that vertex $n-1$ must always be included in the Hamiltonian cycle, and without loss of generality, we can set $x_{n-1,t} = \\delta_{n-1,t}$ for all $t$ and $x_{i,n-1} = \\delta_{i,n-1}$ for all $i$. **This just means that the overall ordering of the cycle is chosen so that vertex $n-1$ comes last.** This reduces the number of qubits to $(n-1)^2$. We adopt this slight modification of the TSP Hamiltonian in our implementation."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:24:25.956145Z",
"start_time": "2021-05-17T08:24:25.950463Z"
}
},
"outputs": [],
"source": [
"# Construct the Hamiltonian H_C in the form of list\n",
"A = 20 # Penalty parameter\n",
"H_C_list = tsp_hamiltonian(G, A, n)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Calculating the loss function \n",
"\n",
"In the [Max-Cut tutorial](./MAXCUT_EN.ipynb), we use a circuit given by QAOA to find the ground state, but we can also use other circuits to solve combinatorial optimization problems. For the TSP, we adopt a parametrized quantum circuit constructed by $U_3(\\vec{\\theta})$ and $\\text{CNOT}$ gates, which we call the [`complex entangled layer`](https://qml.baidu.com/api/paddle_quantum.circuit.uansatz.html).\n",
"\n",
"After running the quantum circuit, we ontain the output circuit $|\\vec{\\theta}\\rangle$. From the output state of the circuit we can calculate the objective function, and also the loss function of the TSP:\n",
"\n",
"$$\n",
"L(\\vec{\\theta}) = \\langle\\vec{\\theta}|H_C|\\vec{\\theta}\\rangle.\n",
"\\tag{6}\n",
"$$\n",
"\n",
"We then use a classical optimization algorithm to minimize this function and find the optimal parameters $\\vec{\\theta}^*$. The following code shows a complete network built with Paddle Quantum and PaddlePaddle."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:24:26.790290Z",
"start_time": "2021-05-17T08:24:26.768068Z"
}
},
"outputs": [],
"source": [
"class Net(paddle.nn.Layer):\n",
" def __init__(self, g, p, H_ls, dtype=\"float64\",):\n",
" super(Net, self).__init__()\n",
" self.p = p\n",
" self.theta = self.create_parameter(shape=[self.p, (len(g.nodes) - 1) ** 2, 3],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * PI),\n",
" dtype=dtype, is_bias=False)\n",
" self.H_ls = H_ls\n",
" self.num_qubits = (len(g) - 1) ** 2\n",
"\n",
" def forward(self):\n",
" # Define a circuit with complex entangled layers\n",
" cir = UAnsatz(self.num_qubits)\n",
" cir.complex_entangled_layer(self.theta, self.p)\n",
" # Run the quantum circuit\n",
" cir.run_state_vector()\n",
" # Calculate the loss function\n",
" loss = cir.expecval(self.H_ls)\n",
"\n",
" return loss, cir"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Training the quantum neural network\n",
"\n",
"After defining the quantum neural network, we use gradient descent method to update the parameters to minimize the expectation value in Eq. (6). "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:24:27.958085Z",
"start_time": "2021-05-17T08:24:27.952965Z"
}
},
"outputs": [],
"source": [
"p = 2 # Number of layers in the quantum circuit\n",
"ITR = 120 # Number of training iterations\n",
"LR = 0.5 # Learning rate of the optimization method based on gradient descent\n",
"SEED = 1000 # Set a global RNG seed "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here, we optimize the network defined above in PaddlePaddle."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:26:08.098742Z",
"start_time": "2021-05-17T08:24:28.741155Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"iter: 10 loss: 46.0238\n",
"iter: 20 loss: 22.6651\n",
"iter: 30 loss: 16.6195\n",
"iter: 40 loss: 14.3719\n",
"iter: 50 loss: 13.5548\n",
"iter: 60 loss: 13.1736\n",
"iter: 70 loss: 13.0661\n",
"iter: 80 loss: 13.0219\n",
"iter: 90 loss: 13.0035\n",
"iter: 100 loss: 13.0032\n",
"iter: 110 loss: 13.0008\n",
"iter: 120 loss: 13.0004\n"
]
}
],
"source": [
"# Fix paddle random seed\n",
"paddle.seed(SEED)\n",
"\n",
"net = Net(G, p, H_C_list)\n",
"# Use Adam optimizer\n",
"opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"# Gradient descent iteration\n",
"for itr in range(1, ITR + 1):\n",
" # Run the network defined above\n",
" loss, cir = net()\n",
" # Calculate the gradient and optimize\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" opt.clear_grad()\n",
" if itr % 10 == 0:\n",
" print(\"iter:\", itr, \" loss:\", \"%.4f\"% loss.numpy())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that ideally the training network will find the shortest Hamiltonian cycle, and the final loss above would correspond to the total weights of the optimal cycle, i.e. the distance of the optimal path for the salesman. If not, then one should adjust parameters of the parameterized quantum circuits above for better training performance."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Decoding the quantum solution\n",
"\n",
"After obtaining the minimum value of the loss function and the corresponding set of parameters $\\vec{\\theta}^*$, our task has not been completed. In order to obtain an approximate solution to the TSP, it is necessary to decode the solution to the classical optimization problem from the quantum state $|\\vec{\\theta}^*\\rangle$ output by the circuit. Physically, to decode a quantum state, we need to measure it and then calculate the probability distribution of the measurement results, where a measurement result is a bit string that represents an answer for the TSP: \n",
"\n",
"$$\n",
"p(z) = |\\langle z|\\vec{\\theta}^*\\rangle|^2.\n",
"\\tag{7}\n",
"$$\n",
"\n",
"Usually, the greater the probability of a certain bit string, the greater the probability that it corresponds to an optimal solution of the TSP.\n",
"\n",
"Paddle Quantum provides a function to read the probability distribution of the measurement results of the state output by the quantum circuit:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:26:08.152206Z",
"start_time": "2021-05-17T08:26:08.103516Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The reduced bit string form of the walk found: 010001100\n"
]
}
],
"source": [
"# Repeat the simulated measurement of the circuit output state 1024 times\n",
"prob_measure = cir.measure(shots=1024)\n",
"reduced_salesman_walk = max(prob_measure, key=prob_measure.get)\n",
"print(\"The reduced bit string form of the walk found:\", reduced_salesman_walk)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As we have slightly modified the TSP Hamiltonian to reduce the number of qubits used, the bit string found above has lost the information for our fixed vertex $n-1$ and the status of other vertices at time $n-1$. So we need to extend the found bit string to include these information.\n",
"\n",
"We need to add a $0$ after every $(n-1)$ bits to represent $x_{i,n-1} = 0$ for $i \\in [0, n-2]$. Then at last, we need to add the bit string representation for vertex $n-1$, i.e. '00...01' with $n-1$ 0s to represent $x_{n-1,t} = 0$ for all $t \\in [0,n-2]$. \n",
"\n",
"After measurement, we have found the bit string with the highest probability of occurrence, the optimal walk in the form of the bit string. Each qubit contains the information of $x_{i,t}$ defined in Eq. (1). The following code maps the bit string back to the classic solution in the form of `dictionary`, where the `key` represents the vertex labeling and the `value` represents its order, i.e. when it is visited. \n",
"\n",
"Also, we have compared it with the solution found by the brute-force algorithm, to verify the correctness of the quantum algorithm."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:26:08.169372Z",
"start_time": "2021-05-17T08:26:08.156656Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The walk found by parameterized quantum circuit: {0: 1, 1: 2, 2: 0, 3: 3} with distance 13\n",
"The walk found by the brute-force algorithm: {0: 0, 1: 1, 2: 3, 3: 2} with distance 13\n"
]
}
],
"source": [
"# Optimal walk found by parameterized quantum circuit\n",
"str_by_vertex = [reduced_salesman_walk[i:i + n - 1] for i in range(0, len(reduced_salesman_walk) + 1, n - 1)]\n",
"salesman_walk = '0'.join(str_by_vertex) + '0' * (n - 1) + '1'\n",
"solution = {i:t for i in range(n) for t in range(n) if salesman_walk[i * n + t] == '1'}\n",
"distance = sum([G[u][v][\"weight\"] if solution[u] == (solution[v] + 1) % n \n",
" or solution[v] == (solution[u] + 1) % n else 0\n",
" for (u, v) in G.edges])\n",
"print(\"The walk found by parameterized quantum circuit:\", solution, \"with distance\", distance)\n",
"\n",
"# Optimal walk found by brute-force algorithm for comparison\n",
"salesman_walk_brute_force, distance_brute_force = solve_tsp_brute_force(G)\n",
"solution_brute_force = {i:salesman_walk_brute_force.index(i) for i in range(n)}\n",
"print(\"The walk found by the brute-force algorithm:\", solution_brute_force, \"with distance\", distance_brute_force)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here, we draw the corresponding optimal walk in the form of graph representation suggested to the salesman:\n",
"* The first number in the vertex represents the city number.\n",
"* The second number in the vertex represents the order the salesman visits the corresponding city.\n",
"* The red edges represent the found optimal route for the salesman."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-05-17T08:26:08.431841Z",
"start_time": "2021-05-17T08:26:08.172882Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 1080x288 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"label_dict = {i: str(i) + \", \" + str(t) for i, t in solution.items()}\n",
"edge_color = [\"red\" if solution[u] == (solution[v] + 1) % n\n",
" or solution[v] == (solution[u] + 1) % n else \"black\"\n",
" for (u, v) in G.edges]\n",
"label_dict_bf = {i: str(i) + \", \" + str(t) for i, t in solution_brute_force.items()}\n",
"edge_color_bf = [\"red\" if solution_brute_force[u] == (solution_brute_force[v] + 1) % n\n",
" or solution_brute_force[v] == (solution_brute_force[u] + 1) % n else \"black\"\n",
" for (u, v) in G.edges]\n",
"\n",
"# Draw the walk corresponding to the dictionary presented above on the graph\n",
"fig, ax = plt.subplots(1, 2, figsize=(15, 4))\n",
"for i, a in enumerate(ax):\n",
" a.axis('off')\n",
" a.margins(0.20)\n",
"nx.draw(G, pos=pos, labels=label_dict, edge_color=edge_color, ax=ax[0], **options)\n",
"nx.drawing.nx_pylab.draw_networkx_edge_labels(G, pos=pos, ax=ax[0], edge_labels=nx.get_edge_attributes(G, 'weight'))\n",
"nx.draw(G, pos=pos, labels=label_dict_bf, edge_color=edge_color_bf, ax=ax[1], **options)\n",
"nx.drawing.nx_pylab.draw_networkx_edge_labels(G, pos=pos, ax=ax[1], edge_labels=nx.get_edge_attributes(G, 'weight'))\n",
"plt.axis(\"off\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The left graph given above shows a solution found by the parameterized quantum circuit, while the right graph given above shows a solution found by the brute-force algorithm. It can be seen that even if the order of the vertices are different, the routes are essentially the same, which verifies the correctness of using parameterized quantum circuit to solve the TSP."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Applications\n",
"\n",
"The TSP naturally applies in many transportation and logistics applications, for example, the problem of arranging school bus routes. The school bus application provides the motivation for Merrill Flood, a pioneer in the field of management science, to study TSP research in the 1940s. More recent applications involve food delivery route management [1] and power delivery for cable firms [2]. \n",
"\n",
"Other than those transportation applications, TSP also has wide usefulness in other management problems like scheduling of a machine to drill holes in a circuit board [3], reconstructing an unknown fragment of DNA [4] and scheduling optimal route in construction management [5]. Some consulting companies like [Nexus](https://nexustech.com.ph/company/newsletter/article/Finding-the-shortest-path-Optimizing-food-trips) have utilized this to provide management service.\n",
"\n",
"The TSP, as one of the most famous optimization problems, also provides a platform for the study of general methods in solving combinatorial problem. This is usually the first several problems that researchers give a try for experiments of new algorithms.\n",
"\n",
"More applications, formulations and solution approaches can be found in [6]."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_______\n",
"\n",
"## References\n",
"\n",
"[1] Bräysy, Olli, et al. \"An optimization approach for communal home meal delivery service: A case study.\" [Journal of Computational and Applied Mathematics 232.1 (2009): 46-53.](https://www.sciencedirect.com/science/article/pii/S0377042708005438)\n",
"\n",
"[2] Sloane, Thomas H., Frank Mann, and H. Kaveh. \"Powering the last mile: an alternative to powering FITL.\" [Proceedings of Power and Energy Systems in Converging Markets. IEEE, 1997.](https://ieeexplore.ieee.org/document/646046)\n",
"\n",
"[3] Onwubolu, Godfrey C. \"Optimizing CNC drilling machine operations: traveling salesman problem-differential evolution approach.\" [New optimization techniques in engineering. Springer, Berlin, Heidelberg, 2004. 537-565.](https://link.springer.com/chapter/10.1007/978-3-540-39930-8_22)\n",
"\n",
"[4] Caserta, Marco, and Stefan Voß. \"A hybrid algorithm for the DNA sequencing problem.\" [Discrete Applied Mathematics 163 (2014): 87-99.](https://www.sciencedirect.com/science/article/pii/S0166218X12003253)\n",
"\n",
"[5] Klanšek, Uroš. \"Using the TSP solution for optimal route scheduling in construction management.\" [Organization, technology & management in construction: an international journal 3.1 (2011): 243-249.](https://www.semanticscholar.org/paper/Using-the-TSP-Solution-for-Optimal-Route-Scheduling-Klansek/3d809f185c03a8e776ac07473c76e9d77654c389)\n",
"\n",
"[6] Matai, Rajesh, Surya Prakash Singh, and Murari Lal Mittal. \"Traveling salesman problem: an overview of applications, formulations, and solution approaches.\" [Traveling salesman problem, theory and applications 1 (2010).](https://www.sciencedirect.com/topics/computer-science/traveling-salesman-problem)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}
......@@ -97,7 +97,7 @@
"source": [
"### 量化纠缠资源\n",
"\n",
"在定性地了解了量子纠缠之后,我们希望能将读者对纠缠的理解提升到一个量化的水平。 首先,我们需要指出上述量子通信协议的有效性,比如量子隐形传态和超密编码,都取决于**纠缠资源的量**,或者说有多少纠缠资源可以被用作为 \"燃料\"去消耗。按照量子信息学界的惯例,**Negativity** $ \\mathcal {N}(\\rho)$ 和 **Logarithmic Negativity** $ E_{N}(\\rho)$ 是公认的可用于量化纠缠资源的指标 [6]。具体的定义如下,\n",
"在定性地了解了量子纠缠之后,我们希望能将读者对纠缠的理解提升到一个量化的水平。 首先,我们需要指出上述量子通信协议的有效性,比如量子隐形传态和超密编码,都取决于**纠缠资源的量**,或者说有多少纠缠资源可以被用作为 \"燃料\"去消耗。按照量子信息学界的惯例,**negativity** $ \\mathcal {N}(\\rho)$ 和 **logarithmic negativity** $ E_{N}(\\rho)$ 是公认的可用于量化纠缠资源的指标 [6]。具体的定义如下,\n",
"\n",
"$$\n",
"\\mathcal{N}(\\rho) \\equiv \\frac{||\\rho^{T_B}||_1-1}{2},\n",
......@@ -191,7 +191,7 @@
"id": "needed-arkansas",
"metadata": {},
"source": [
"在纠缠蒸馏方案中,我们通常使用蒸馏后的输出态 $\\rho_{out}$ 和贝尔态 $|\\Phi^+\\rangle$ 之间的**保真度 (state fidelity)** $ F $ 来量化蒸馏方案的性能,其中\n",
"在纠缠蒸馏方案中,我们通常使用蒸馏后的输出态 $\\rho_{out}$ 和贝尔态 $|\\Phi^+\\rangle$ 之间的**保真度(state fidelity)**$F$ 来量化蒸馏方案的性能,其中\n",
"\n",
"$$\n",
"F(\\rho_{out}, \\Phi^+) \\equiv \\langle \\Phi^+|\\rho_{out}|\\Phi^+\\rangle.\n",
......@@ -243,10 +243,9 @@
"source": [
"经过以上准备,我们可以开始介绍 BBPSSW 协议。\n",
"\n",
"\n",
"## BBPSSW 协议\n",
"\n",
"BBPSSW 协议将两份相同的两方量子态 $\\rho_{in}$ 蒸馏成输出态 $\\rho_{out}$,一份具有更高的保真度 $ F $(更接近贝尔态 $|\\Phi^+\\rangle$)的两方量子态。值得注意的是,BBPSSW 主要用于蒸馏 **Isotropic 态**(也称为 Werner 态),由 $|\\Phi^+\\rangle$ 和完全混合态(白噪声)$I/4$ 组成。\n",
"BBPSSW 协议将两份相同的两方量子态 $\\rho_{in}$ 蒸馏成输出态 $\\rho_{out}$,一份具有更高的保真度 $ F $(更接近贝尔态 $|\\Phi^+\\rangle$)的两方量子态。值得注意的是,BBPSSW 主要用于蒸馏 **isotropic 态**(也称为 Werner 态),由 $|\\Phi^+\\rangle$ 和完全混合态(白噪声)$I/4$ 组成。\n",
"\n",
"$$\n",
"\\rho_{\\text{iso}}(p) = p\\lvert\\Phi^+\\rangle \\langle\\Phi^+\\rvert + (1-p)\\frac{I}{4}, \\quad p \\in [0,1]\n",
......@@ -258,7 +257,7 @@
"BBPSSW 蒸馏协议由两个远程参与方 $ A $(Alice)和 $ B $(Bob)执行。它们共享两份量子对 $ \\rho_{A_0B_0} $ 和 $ \\rho_{A_1B_1} $。每对的初始态均为 $ \\rho_ {in} = \\rho _ {\\text {iso}}(p)$。Alice 拥有两个量子比特 $ A_0,A_1 $,Bob 也拥有两个量子比特 $ B_0,B_1 $。通过这些初始设置,Alice 和 Bob 需要实现以下流程:\n",
"\n",
"1. Alice 和 Bob 先选择任意一对量子比特,**这对量子比特将作为最终的输出比特**。这里假设他们选择了 $A_0$ 和 $B_0$。\n",
"2. Alice 和 Bob 对他们手中的量子比特施加受控非门 (CNOT 门)。这里, $A_0$ 和 $B_0$ 作为控制比特,$A_1$ 和 $B_1$ 作为目标比特。\n",
"2. Alice 和 Bob 对他们手中的量子比特施加受控非门(CNOT 门)。这里, $A_0$ 和 $B_0$ 作为控制比特,$A_1$ 和 $B_1$ 作为目标比特。\n",
"3. 接下来双方分别对 $A_1$ 和 $B_1$ 进行测量,并通过**经典通讯**来交换他们的测量结果 $m_{A_1}, m_{B_1}$。\n",
"4. 如果 Alice 和 Bob 的结果一致(00或11),那么他们可以宣布本次蒸馏过程成功,同时将 $A_0$ 和 $B_0$ 作为输出比特,输出态为 $\\rho_{out}$。相反,如果他们的测量结果不一致(01或10),那么本次蒸馏过程失败,丢弃量子比特 $A_0$ 和 $B_0$。无论蒸馏成功与否,测量之后的量子比特 $A_1,B_1$ 都不会再被使用。\n",
"\n",
......@@ -282,7 +281,7 @@
"\n",
"在下一节中,我们将介绍如何使用量桨模拟 BBPSSW 协议。\n",
"\n",
"**注释:** 如果输入态不是 Isotropic 态 ,则可以通过概率性的旋转操作将其去极化(depolarize)为 Isotropic 态。"
"**注释:** 如果输入态不是 isotropic 态 ,则可以通过概率性的旋转操作将其去极化(depolarize)为 isotropic 态。"
]
},
{
......@@ -583,7 +582,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.9"
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
......
......@@ -91,7 +91,7 @@
"source": [
"### Entanglement quantification\n",
"\n",
"After having a taste of quantum entanglement qualitatively, we want to promote our understanding to a quantitive level. One should realize the validity of aforementioned quantum communication protocols, including quantum teleportation and superdense coding, depends on **the quality of the entanglement quantification**. Following the convention in quantum information community, the **Negativity** $\\mathcal{N}(\\rho)$ and the **Logarithmic Negativity** $E_{N}(\\rho)$ are widely recognized metrics to quantify the amount of entanglement presented in a bi-partite system [6]. Specifically,\n",
"After having a taste of quantum entanglement qualitatively, we want to promote our understanding to a quantitive level. One should realize the validity of aforementioned quantum communication protocols, including quantum teleportation and superdense coding, depends on **the quality of the entanglement quantification**. Following the convention in quantum information community, the **negativity** $\\mathcal{N}(\\rho)$ and the **logarithmic negativity** $E_{N}(\\rho)$ are widely recognized metrics to quantify the amount of entanglement presented in a bi-partite system [6]. Specifically,\n",
"\n",
"$$\n",
"\\mathcal{N}(\\rho) \\equiv \\frac{||\\rho^{T_B}||_1-1}{2},\n",
......@@ -240,7 +240,7 @@
"source": [
"## BBPSSW protocol\n",
"\n",
"The BBPSSW protocol distills two identical quantum states $\\rho_{in}$ (2-copies) into a single final state $\\rho_{out}$ with a higher state fidelity $F$ (closer to the Bell state $|\\Phi^+\\rangle$). It is worth noting that BBPSSW was mainly designed to purify **Isotropic states** (also known as Werner state), a parametrized family of mixed states consist of $|\\Phi^+\\rangle$ and the completely mixed state (white noise) $I/4$.\n",
"The BBPSSW protocol distills two identical quantum states $\\rho_{in}$ (2-copies) into a single final state $\\rho_{out}$ with a higher state fidelity $F$ (closer to the Bell state $|\\Phi^+\\rangle$). It is worth noting that BBPSSW was mainly designed to purify **isotropic states** (also known as Werner state), a parametrized family of mixed states consist of $|\\Phi^+\\rangle$ and the completely mixed state (white noise) $I/4$.\n",
"\n",
"$$\n",
"\\rho_{\\text{iso}}(p) = p\\lvert\\Phi^+\\rangle \\langle\\Phi^+\\rvert + (1-p)\\frac{I}{4}, \\quad p \\in [0,1]\n",
......@@ -568,7 +568,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.9"
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
......
......@@ -38,7 +38,7 @@
"\n",
"这里我们假设 $p_1 > p_2 \\geq p_3 \\geq p_4$,并且满足 $p_1 + p_2+ p_3+ p_4 = 1$。那么,我们可以通过以下方式刻画贝尔对角态的纠缠度:\n",
"\n",
"* 保真度 (State fidelity):$F = \\langle \\Phi^+|\\rho_{\\text{diag}}|\\Phi^+\\rangle = p_1$\n",
"* 保真度 (state fidelity):$F = \\langle \\Phi^+|\\rho_{\\text{diag}}|\\Phi^+\\rangle = p_1$\n",
"* Negativity: $\\mathcal{N}(\\rho_{\\text{diag}}) = p_1 - 1/2$\n",
"\n",
"**提示:** 贝尔对角态仅能在 $p_1 > 1/2$ 时才能通过蒸馏提高保真度。"
......@@ -54,7 +54,7 @@
"\n",
"1. Alice 和 Bob 先选择任意一对量子比特,**这对量子比特将作为最终的输出比特**。这里假设他们选择了 $A_0$ 和 $B_0$。\n",
"2. 首先,Alice 对她的两个量子比特施加旋转门 $R_x(\\pi/2)$ ,Bob对他的量子比特施加旋转门 $R_x(-\\pi/2)$。\n",
"3. 之后,Alice 和 Bob 对他们手中的量子比特施加受控非门 (CNOT 门)。这里, $A_0$ 和 $B_0$ 作为控制比特,$A_1$ 和 $B_1$ 作为目标比特。\n",
"3. 之后,Alice 和 Bob 对他们手中的量子比特施加受控非门(CNOT 门)。这里, $A_0$ 和 $B_0$ 作为控制比特,$A_1$ 和 $B_1$ 作为目标比特。\n",
"4. 接下来双方分别对 $A_1$ 和 $B_1$ 进行测量,并通过**经典通讯**来交换他们的测量结果 $m_{A_1}, m_{B_1}$。\n",
"5. 如果Alice和Bob的结果一致(00或11),那么他们可以宣布本次蒸馏过程成功,同时 $A_0$ 和 $B_0$ 作为输出比特,输出态为 $\\rho_{out}$。相反,如果他们的测量结果不一致(01或10),那么本次蒸馏过程失败,丢弃量子比特 $A_0$ 和 $B_0$。\n",
"\n",
......@@ -342,7 +342,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.9"
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
......
......@@ -42,7 +42,7 @@
"source": [
"### 协议的设计逻辑\n",
"\n",
"在本教程中,我们用4份相同的 **Isotropic 态** (也被称为 Werner 态)蒸馏出一份具有更高保真度输出态(相较于初始态,输出态更接近贝尔态 $|\\Phi^+\\rangle$)。这种协议被称为 $4\\rightarrow 1$ LOCC 蒸馏协议。相对应的,BBPSSW 和 DEJMPS 协议属于 $2\\rightarrow 1$ LOCC 蒸馏协议(因为一开始使用了2份相同的初始态)。\n",
"在本教程中,我们用4份相同的 **isotropic 态** (也被称为 Werner 态)蒸馏出一份具有更高保真度输出态(相较于初始态,输出态更接近贝尔态 $|\\Phi^+\\rangle$)。这种协议被称为 $4\\rightarrow 1$ LOCC 蒸馏协议。相对应的,BBPSSW 和 DEJMPS 协议属于 $2\\rightarrow 1$ LOCC 蒸馏协议(因为一开始使用了2份相同的初始态)。\n",
"Isotropic 态是由 $|\\Phi^+\\rangle$ 和完全混合态(白噪声)$I/4$ 组成,\n",
"\n",
"$$\n",
......@@ -57,7 +57,7 @@
"\\tag{3}\n",
"$$\n",
"\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",
"为了通过 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",
"1. 设计一个 QNN 架构 $U(\\boldsymbol\\theta)$ 如图 1所示,其中 $R(\\theta)$ 表示单比特通用门。我们可以通过调用 Paddle Quantum 中的 `u3(theta, phi, lam, which_qubit)` 来实现该旋转门。\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",
......@@ -187,7 +187,7 @@
" status1 = self.measure(status, [[\"Alice\", 1], [\"Bob\", 1],[\"Alice\", 2], [\"Bob\", 2], [\"Alice\", 3], [\"Bob\", 3]], \n",
" [\"000000\", \"000011\", \"001100\", \"110000\", \"001111\", \"111100\", \"110011\", \"111111\"])\n",
" \n",
" # 取偏迹除去测量后的量子比特,只留下 A0&B0 \n",
" # 取偏迹除去测量后的量子比特,只留下 A0 & B0 \n",
" status_fin = self.partial_state(status1, [[\"Alice\", 0], [\"Bob\", 0]])\n",
" target_state = paddle.to_tensor(bell_state(2))\n",
" \n",
......
......@@ -15,7 +15,7 @@
"source": [
"## 概述\n",
"\n",
"量子纠缠在量子通信、量子计算以及其他量子技术中是一种很重要的资源。因此,能否在这些领域构建出实际的应用,很大程度上取决于我们能否有效地利用量子纠缠这一资源。在 NISQ (Noisy Intermediate-Scale Quantum)时代,通过量子网络实现两个节点之间直接通讯量子信息是一项艰巨的任务。所以在当前阶段,通过本地操作和经典通讯(LOCC)[1] 来完成特定任务,是比全局操作(Global Operation)更为有效的方式。所谓本地操作和经典通讯,是指几个空间上分离的参与者只能在自己的实验室中执行本地操作,然后通过经典通讯的方式传递他们经典信息(可以是测量结果)。然而,设计 LOCC 协议来进行纠缠操作以及分布式量子信息处理是非常具有挑战性的,因为 LOCC 的结构通常很复杂并且很难用数学方法描述。为了更好地探索如何在近期量子设备上利用量子纠缠资源以及从长远角度来看进行分布式量子信息处理,我们设计了 **LOCCNet**,一种用于 LOCC 协议设计的机器学习框架 [2]。"
"量子纠缠在量子通信、量子计算以及其他量子技术中是一种很重要的资源。因此,能否在这些领域构建出实际的应用,很大程度上取决于我们能否有效地利用量子纠缠这一资源。在 NISQ (noisy intermediate-scale quantum)时代,通过量子网络实现两个节点之间直接通讯量子信息是一项艰巨的任务。所以在当前阶段,通过本地操作和经典通讯(LOCC)[1] 来完成特定任务,是比全局操作(global operation)更为有效的方式。所谓本地操作和经典通讯,是指几个空间上分离的参与者只能在自己的实验室中执行本地操作,然后通过经典通讯的方式传递他们经典信息(可以是测量结果)。然而,设计 LOCC 协议来进行纠缠操作以及分布式量子信息处理是非常具有挑战性的,因为 LOCC 的结构通常很复杂并且很难用数学方法描述。为了更好地探索如何在近期量子设备上利用量子纠缠资源以及从长远角度来看进行分布式量子信息处理,我们设计了 **LOCCNet**,一种用于 LOCC 协议设计的机器学习框架 [2]。"
]
},
{
......@@ -24,7 +24,7 @@
"source": [
"## 什么是 LOCC?\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)$。比如量子隐形传态协议 [3] 就是一个一轮通讯两个参与方的协议 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",
"<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 @@
"<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",
"这些协议看上去十分简单,但是当参与方增多而且通讯轮数变多时,想要找到每一个参与方的最优的本地操作就会变得十分困难。现在我们大致了解了为什么说设计一个 LOCC 协议是一项艰巨的任务。即使如此困难,仍有许多重要的 LOCC 协议被科学家提了出来,比如:纠缠蒸馏(Entanglement Distillation) [4-5],纠缠转换(Entanglement Swapping) [6-7] 等。\n"
"这些协议看上去十分简单,但是当参与方增多而且通讯轮数变多时,想要找到每一个参与方的最优的本地操作就会变得十分困难。现在我们大致了解了为什么说设计一个 LOCC 协议是一项艰巨的任务。即使如此困难,仍有许多重要的 LOCC 协议被科学家提了出来,比如:纠缠蒸馏(entanglement distillation) [4-5],纠缠转换(entanglement swapping) [6-7] 等。\n"
]
},
{
......@@ -46,7 +46,7 @@
"source": [
"## LOCCNet 的设计理念\n",
"\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",
"我们从机器学习解决量子多体问题 [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",
"**注释:** 当前版本下,LOCCNet 仅支持密度矩阵形式。"
......@@ -127,7 +127,6 @@
"- [量子隐态传输](QuantumTeleportation_CN.ipynb)\n",
"- [量子态分辨](StateDiscrimination_CN.ipynb)\n",
"\n",
"\n",
"LOCCNet 框架所能做的远不止上述几个方向,我们希望您可以使用这个新框架去探索更多有趣的协议!"
]
},
......
......@@ -15,7 +15,7 @@
"source": [
"## 概述\n",
"\n",
"量子隐形传态(Quantum Teleportation)是可以通过本地操作和经典通信(LOCC)协议完成的另一项重要任务,该协议借助提前制备好的纠缠资源在两个空间上分离的通信节点(仅允许经典信道)之间传输量子信息。在本教程中,我们将首先简要回顾一下量子隐形传态协议,并使用量桨进行模拟。然后,我们将介绍如何使用 LOCCNet 学习出一个量子隐形传态协议。"
"量子隐形传态(quantum teleportation)是可以通过本地操作和经典通信(LOCC)协议完成的另一项重要任务,该协议借助提前制备好的纠缠资源在两个空间上分离的通信节点(仅允许经典信道)之间传输量子信息。在本教程中,我们将首先简要回顾一下量子隐形传态协议,并使用量桨进行模拟。然后,我们将介绍如何使用 LOCCNet 学习出一个量子隐形传态协议。"
]
},
{
......@@ -631,7 +631,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.7.0"
},
"toc": {
"base_numbering": 1,
......
......@@ -2,6 +2,7 @@
"cells": [
{
"cell_type": "markdown",
"id": "dda97799",
"metadata": {},
"source": [
"# 利用 LOCC 来进行两方量子态分辨\n",
......@@ -12,15 +13,17 @@
},
{
"cell_type": "markdown",
"id": "4942c442",
"metadata": {},
"source": [
"## 概述\n",
"\n",
"量子态分辨(Quantum State Discrimination, QSD)[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",
"id": "e7347c1f",
"metadata": {},
"source": [
"## 寻找一个态分辨协议\n",
......@@ -54,6 +57,7 @@
},
{
"cell_type": "markdown",
"id": "d09e6486",
"metadata": {},
"source": [
"## Paddle Quantum 代码实现\n",
......@@ -64,6 +68,7 @@
{
"cell_type": "code",
"execution_count": 1,
"id": "5fc7fce4",
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T04:10:28.022626Z",
......@@ -80,6 +85,7 @@
},
{
"cell_type": "markdown",
"id": "5c5a100c",
"metadata": {},
"source": [
"Charlie 需要随机生成两个正交态 $\\lvert\\psi\\rangle$ 以及 $\\lvert\\phi\\rangle$。"
......@@ -88,6 +94,7 @@
{
"cell_type": "code",
"execution_count": 2,
"id": "9abe8856",
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T04:10:38.723834Z",
......@@ -109,6 +116,7 @@
},
{
"cell_type": "markdown",
"id": "724e5c48",
"metadata": {},
"source": [
"下面是我们代码的主要部分,它定义了 Alice 和 Bob 的本地量子操作和损失函数。"
......@@ -117,6 +125,7 @@
{
"cell_type": "code",
"execution_count": 3,
"id": "9cca865a",
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T04:10:39.769534Z",
......@@ -241,6 +250,7 @@
},
{
"cell_type": "markdown",
"id": "1e648ea7",
"metadata": {},
"source": [
"训练 Alice 和 Bob 的电路,然后随机选择两个正交态 $\\lvert\\psi\\rangle$ 和 $\\lvert\\phi\\rangle$ 之一以通过我们训练的电路,以检查它们是否可以区分。"
......@@ -249,6 +259,7 @@
{
"cell_type": "code",
"execution_count": 4,
"id": "3c722a55",
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T04:10:45.887729Z",
......@@ -311,6 +322,7 @@
},
{
"cell_type": "markdown",
"id": "32c38151",
"metadata": {},
"source": [
"## 结论\n",
......@@ -320,6 +332,7 @@
},
{
"cell_type": "markdown",
"id": "249db983",
"metadata": {},
"source": [
"---\n",
......@@ -349,7 +362,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.7.0"
},
"toc": {
"base_numbering": 1,
......
{
"cells": [
{
"cell_type": "markdown",
"id": "dddbe576",
"metadata": {},
"source": [
"# 量子态编码经典数据\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "9ddf4180",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>pre { white-space: pre !important; }</style>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.core.display import HTML\n",
"display(HTML(\"<style>pre { white-space: pre !important; }</style>\"))"
]
},
{
"cell_type": "markdown",
"id": "93be1348",
"metadata": {},
"source": [
"## 概览\n",
"\n",
"量子编码是一个将经典信息转化为量子态的过程。在使用量子算法解决经典问题的过程中,量子编码是非常重要的一步。比如在[量子分类器](./QClassifier_CN.ipynb)中,第一步就是将经典信息转变为可以传入量子电路的量子态。大多数量子编码的方法都可以看作是作用在 $\\left| 0^n \\right>$ 态上的参数化电路,并且参数化电路中的参数是由经典信息决定。\n",
"\n",
"本教程中我们将讨论五种量子编码的方式,包括**基态编码** [1]、**振幅编码** [1]、**角度编码** [1]、**IQP 编码** [2]和**哈密顿量演化编码** [3]。在量桨中,我们内置了前四种量子编码方式。\n",
"\n",
"## 基态编码\n",
"\n",
"基态编码(basis encoding)是最直观的一种编码方式。它把一个长度为 $n$ 的二进制字符串 $x$ 转化为一个有 $n$ 个量子比特的量子态 $\\left|x\\right> = \\left|i_x\\right>$。其中,$\\left|i_x\\right>$ 是一个计算基态。比如说,当经典数据为 $x=1011$ 时,对应得到的量子态就是 $\\left|1011\\right>$。下面,我们来看看如何使用量桨实现基态编码:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "44bd5d8e",
"metadata": {},
"outputs": [],
"source": [
"# 导入所需要的包\n",
"import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"id": "59ef733b",
"metadata": {},
"source": [
"从 $\\left| 0^n \\right>$ 开始,如果第 $i$ 位的经典信息是1,那么我们在对应的第 $i$ 个量子比特上作用一个 $X$ 门:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "eee7f90d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--X--\n",
" \n",
"-----\n",
" \n",
"--X--\n",
" \n",
"--X--\n",
" \n"
]
}
],
"source": [
"# 量子比特的数量等于经典信息的长度\n",
"n = 4\n",
"# 初始化电路\n",
"basis_enc = UAnsatz(n)\n",
"# x 是经典信息\n",
"x = '1011'\n",
"# 如果第 i 维经典信息是1,那么我们在对应的量子比特上作用一个 X 门\n",
"for i in range(len(x)):\n",
" if x[i] == '1':\n",
" basis_enc.x(i)\n",
" \n",
"print(basis_enc)"
]
},
{
"cell_type": "markdown",
"id": "4e1525b7",
"metadata": {},
"source": [
"可以看到经过基态编码后的量子态为:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "6293b67b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j\n",
" 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n"
]
}
],
"source": [
"basis_quan_state = basis_enc.run_state_vector()\n",
"print(basis_quan_state.numpy())"
]
},
{
"cell_type": "markdown",
"id": "8703d88f",
"metadata": {},
"source": [
"这就是我们想要得到的 $\\left|1011\\right>$ 态。\n",
"\n",
"在量桨中,我们提供内置的基态编码函数:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "3f58d5a3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j\n",
" 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n"
]
}
],
"source": [
"# 内置的基态编码函数\n",
"built_in_basis_enc = UAnsatz(n)\n",
"# 经典信息 x 需要是 Tensor 的形式\n",
"x = paddle.to_tensor([1, 0, 1, 1])\n",
"built_in_basis_enc.basis_encoding(x)\n",
"built_in_basis_enc_state = built_in_basis_enc.run_state_vector()\n",
"print(built_in_basis_enc_state.numpy())"
]
},
{
"cell_type": "markdown",
"id": "30f059ba",
"metadata": {},
"source": [
"## 振幅编码\n",
"\n",
"振幅编码(amplitude encoding)将一个 $N$ 维的经典向量 $\\mathbf{x}$ 编码到一个有 $n$ 个量子比特的量子态,其中 $n = \\lceil\\log_2(N)\\rceil$,且\n",
"\n",
"$$\n",
"\\begin{align*} \\left|\\mathbf{x}\\right> = \\sum\\limits_{i}^{N}x_i\\left|i\\right>\\end{align*},\n",
"$$\n",
"\n",
"这里,$\\left\\{\\left|i\\right>\\right\\}$ 是希尔伯特空间的一组计算基。因为经典信息构成了一个量子态的振幅,所以这个经典信息需要满足归一化条件:$\\left|\\mathbf{x}\\right|^{2} = 1$。 \n",
"比如说,当 $\\mathbf{x} = \\begin{bmatrix} \\frac{1}{2}\\\\ \\frac{1}{2}\\\\ -\\frac{1}{2}\\\\ -\\frac{1}{2} \\end{bmatrix}$ 时,编码后得到的量子态就是 $\\left|\\mathbf{x}\\right> = \\frac{1}{2}\\left|00\\right> + \\frac{1}{2} \\left|01\\right> - \\frac{1}{2} \\left|10\\right> - \\frac{1}{2} \\left|11\\right>$。 \n",
"我们也举一个当 $N$ 小于 $2^{n}$ 时的例子,如果 $\\mathbf{y} = \\begin{bmatrix} \\frac{1}{\\sqrt{3}}\\\\\\frac{1}{\\sqrt{3}}\\\\\\frac{1}{\\sqrt{3}} \\end{bmatrix}$, 那么对应的量子态就是$\\left|\\mathbf{y}\\right> = \\frac{1}{\\sqrt{3}}\\left|00\\right> + \\frac{1}{\\sqrt{3}}\\left|01\\right> + \\frac{1}{\\sqrt{3}}\\left|10\\right>$。\n",
"\n",
"显然,振幅编码无法简单地被表示为电路的形式。实际上,振幅编码的实现需要用到一种叫做任意态制备的方法 [1]。但不用担心,在量桨中,我们提供了内置的振幅编码函数可以直接使用:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "2436b99f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0.57735026+0.j 0.57735026+0.j 0.57735026+0.j 0. +0.j]\n"
]
}
],
"source": [
"# 内置振幅编码函数\n",
"# 量子比特的数目为2\n",
"n = 2\n",
"# 初始化电路\n",
"built_in_amplitude_enc = UAnsatz(n)\n",
"# 经典信息 x 需要是 Tensor 的形式\n",
"x = paddle.to_tensor([0.5, 0.5, 0.5])\n",
"state = built_in_amplitude_enc.amplitude_encoding(x, 'state_vector')\n",
"print(state.numpy())"
]
},
{
"cell_type": "markdown",
"id": "14fc67cd",
"metadata": {},
"source": [
"在量桨中,我们会默认归一化输入的经典向量。可以看到,编码后得到的量子态就是 $\\frac{1}{\\sqrt{3}}\\left|00\\right> + \\frac{1}{\\sqrt{3}}\\left|01\\right> + \\frac{1}{\\sqrt{3}}\\left|10\\right>$。\n",
"\n",
"## 角度编码\n",
"\n",
"角度编码(angle encoding)运用了旋转门来编码经典信息 $\\mathbf{x}$,这些旋转门的旋转角度由经典信息决定,\n",
"\n",
"$$\n",
"\\left|\\mathbf{x}\\right> = \\bigotimes_{i}^{n} R(\\mathbf{x}_i) \\left| 0^n \\right>,\n",
"$$\n",
"\n",
"在这里可以使用 $R_x$、$R_y$ 和 $R_z$ 中的任意一种来作为 $R$。通常情况下,量子比特的数量是等于经典信息的维度的。\n",
"比如说,当 $\\mathbf{x} = \\begin{bmatrix} \\pi \\\\ \\pi\\\\ \\pi \\end{bmatrix}$ 时,如果我们使用 $R_y$,那么角度编码就会使每个量子比特绕 $y$ 轴旋转$180$度,对应的量子态就会是 $\\left|111\\right>$。\n",
"\n",
"我们可以通过如下方法构造角度编码的电路:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "bbfd0d21",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--Ry(3.142)--\n",
" \n",
"--Ry(3.142)--\n",
" \n",
"--Ry(3.142)--\n",
" \n"
]
}
],
"source": [
"# 量子比特的数量等于经典信息的维度\n",
"n = 3\n",
"# 初始化电路\n",
"angle_enc = UAnsatz(n)\n",
"# x 是需要编码的经典信息\n",
"x = paddle.to_tensor([np.pi, np.pi, np.pi], 'float64')\n",
"# 加一层 Ry 旋转门\n",
"for i in range(len(x)):\n",
" angle_enc.ry(x[i], i)\n",
" \n",
"print(angle_enc)"
]
},
{
"cell_type": "markdown",
"id": "d062e164",
"metadata": {},
"source": [
"对应编码后的量子态就是:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "5905b719",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0j, 0j, 0j, 0j, 0j, 0j, 0j, (1+0j)]\n"
]
}
],
"source": [
"angle_quan_state = angle_enc.run_state_vector()\n",
"print([np.round(i, 2) for i in angle_quan_state.numpy()])"
]
},
{
"cell_type": "markdown",
"id": "33a722a2",
"metadata": {},
"source": [
"正是我们想要的 $\\left|111\\right>$。\n",
"\n",
"在量桨中,我们也提供了内置的角度编码的函数:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "7462102b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0j, 0j, 0j, 0j, 0j, 0j, 0j, (1+0j)]\n"
]
}
],
"source": [
"# 内置角度编码函数\n",
"# 量子比特的数目是3\n",
"n = 3\n",
"# 初始化电路\n",
"built_in_angle_enc = UAnsatz(n)\n",
"# x是需要编码的经典信息\n",
"x = paddle.to_tensor([np.pi, np.pi, np.pi], 'float64')\n",
"built_in_angle_enc.angle_encoding(x, \"ry\")\n",
"state = built_in_angle_enc.run_state_vector()\n",
"print([np.round(i, 2) for i in state.numpy()])"
]
},
{
"cell_type": "markdown",
"id": "c11672af",
"metadata": {},
"source": [
"## IQP 编码\n",
"\n",
"IQP 编码(instantaneous quantum polynomial style encoding)是一个相对来说比较复杂的编码方式。我们把一个经典信息 $\\mathbf{x}$ 编码到\n",
"\n",
"$$\n",
"\\left|\\mathbf{x}\\right> = \\left(\\mathrm{U}_\\mathrm{Z}(\\mathbf{x})\\mathrm{H}^{\\otimes n}\\right)^{r}\\left|0^n\\right>,\n",
"$$\n",
"\n",
"在这里,$r$ 表示电路的深度,也就是 $\\mathrm{U}_\\mathrm{Z}(\\mathbf{x})\\mathrm{H}^{\\otimes n}$ 重复的次数。$\\mathrm{H}^{\\otimes n}$ 是一层作用在所有量子比特上的Hadamard门。$\\mathrm{U}_\\mathrm{Z}(\\mathbf{x})$ 则是 IQP 编码中最重要的一步:\n",
"\n",
"$$\n",
"\\mathrm{U}_\\mathrm{Z}(\\mathbf{x})=\\prod\\limits_{[i,j]\\in S}R_{Z_iZ_j}(x_ix_j)\\bigotimes_{k=1}^{n} R_z(x_k),\n",
"$$\n",
"\n",
"这里的 $S$ 是一个集合,对于这个集合中的每一对量子比特,我们都需要对它们作用 $R_{ZZ}$ 门。\n",
"\n",
"首先我们考虑一个简单的两量子比特门:$R_{Z_1Z_2}(\\theta)$。它的数学表达式 $e^{-i\\frac{\\theta}{2}Z_1\\otimes Z_2}$ 可以看做是绕 ZZ 旋转的两比特旋转门,并且使得这两个量子比特纠缠。我们可以使用如下方法在量桨中实现这个门:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "4ed6549a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--*-----------------*--\n",
" | | \n",
"--X----Rz(6.000)----X--\n",
" \n"
]
}
],
"source": [
"# 量子比特的数量\n",
"n = 2\n",
"# 初始化电路\n",
"Rzz = UAnsatz(n)\n",
"# x 是经典信息\n",
"x = paddle.to_tensor([2, 3], 'float64')\n",
"# 实现 RZZ 门\n",
"Rzz.cnot([0, 1])\n",
"Rzz.rz(x[0]*x[1], 1)\n",
"Rzz.cnot([0, 1])\n",
" \n",
"print(Rzz)"
]
},
{
"cell_type": "markdown",
"id": "cafaed9d",
"metadata": {},
"source": [
"在 $\\mathrm{U}_\\mathrm{Z}$中,$R_{ZZ}$ 会作用在每一对属于集合 $S$ 的量子比特对上。在量桨内置的 IQP 编码函数中,用户可以自定义这个集合 $S$。\n",
"\n",
"现在我们来看看如何使用量桨实现这个电路:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "05abe637",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--H----Rz(-1.45)----*-----------------*------------------------------------------------\n",
" | | \n",
"--H----Rz(3.000)----X----Rz(-4.35)----X----*-----------------*-------------------------\n",
" | | \n",
"--H----Rz(2.000)---------------------------X----Rz(6.000)----X----*-----------------*--\n",
" | | \n",
"--H----Rz(-0.05)--------------------------------------------------X----Rz(-0.10)----X--\n",
" \n"
]
}
],
"source": [
"# 量子比特的数量\n",
"n = 4\n",
"# 初始化电路\n",
"iqp_enc = UAnsatz(n)\n",
"# x 是经典信息\n",
"x = paddle.to_tensor([-1.45, 3, 2, -0.05], 'float64')\n",
"# S 集合中的每一对量子比特对都要加上 RZZ 门\n",
"S = [[0, 1], [1, 2], [2, 3]]\n",
"r = 1\n",
"\n",
"for i in range(r):\n",
" # 加上一层 Hadamard 门\n",
" iqp_enc.superposition_layer()\n",
" # 加上一层旋转门 Rz\n",
" for j in range(n):\n",
" iqp_enc.rz(x[j] ,j)\n",
" # 加上 RZZ 门\n",
" for k in S:\n",
" iqp_enc.cnot(k)\n",
" iqp_enc.rz(x[k[0]]*x[k[1]], k[1])\n",
" iqp_enc.cnot(k)\n",
" \n",
"print(iqp_enc)"
]
},
{
"cell_type": "markdown",
"id": "ef8bffcb",
"metadata": {},
"source": [
"编码后的量子态是:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "0c84ae1f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[(0.25+0j), (0.24719-0.03736j), (-0.0115+0.24974j), (-0.02397+0.24885j), (-0.01559-0.24951j), (-0.0527-0.24438j), (0.21313+0.13067j), (0.20633+0.14116j), (0.22138+0.11615j), (0.23625+0.08176j), (-0.12621+0.2158j), (-0.13684+0.20922j), (0.07483+0.23854j), (0.10964+0.22468j), (-0.2382-0.07589j), (-0.23411-0.0877j)]\n"
]
}
],
"source": [
"iqp_quan_state = iqp_enc.run_state_vector()\n",
"print([np.round(i, 5) for i in iqp_quan_state.numpy()])"
]
},
{
"cell_type": "markdown",
"id": "1ab76781",
"metadata": {},
"source": [
"在量桨中,我们提供了内置的 IQP 编码函数。需要注意的是,我们上述描述的这种 IQP 编码仅仅是 IQP 编码方式这个大类中的一个特例。在更为广义的 IQP 编码方式中,你可以把 $R_{Z}$ 替换为 $R_{Y}$ 或者 $R_{X}$,还可以把 $R_{ZZ}$ 替换为 $R_{XX}$ 或者 $R_{YY}$。除此之外,你甚至可以考虑三量子比特旋转门,并在 $\\mathrm{U}(\\mathbf{x})$ 的后面加上多层三量子比特旋转门。"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "b941cb2e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[(0.25+0j), (0.24719-0.03736j), (-0.0115+0.24974j), (-0.02397+0.24885j), (-0.01559-0.24951j), (-0.0527-0.24438j), (0.21313+0.13067j), (0.20633+0.14116j), (0.22138+0.11615j), (0.23625+0.08176j), (-0.12621+0.2158j), (-0.13684+0.20922j), (0.07483+0.23854j), (0.10964+0.22468j), (-0.2382-0.07589j), (-0.23411-0.0877j)]\n"
]
}
],
"source": [
"# 内置 IQP 编码\n",
"# 量子比特的数量是 6\n",
"n = 4\n",
"# 初始化电路\n",
"built_in_iqp_enc = UAnsatz(n)\n",
"# x 是经典信息\n",
"x = paddle.to_tensor([-1.45, 3, 2, -0.05], 'float64')\n",
"# S 集合中的每一对量子比特对都要加上 RZZ 门\n",
"S = [[0, 1], [1, 2], [2, 3]]\n",
"# r 是 U 重复的次数\n",
"r = 1\n",
"built_in_iqp_enc.iqp_encoding(x, r, S)\n",
"built_in_iqp_enc_state = built_in_iqp_enc.run_state_vector()\n",
"print([np.round(i, 5) for i in built_in_iqp_enc_state.numpy()])"
]
},
{
"cell_type": "markdown",
"id": "9d5f4d71",
"metadata": {},
"source": [
"## 哈密顿量演化编码\n",
"\n",
"哈密顿量演化编码(Hamiltonian evolution ansatz encoding)运用了特罗特公式(Trotter formula)来近似一个演化,获取哈伯特模型(Hubbard model)的基态能量就使用了这种编码方式 [4]。\n",
"\n",
"$$\n",
"\\left|\\mathbf{x}\\right> = \\left(\\prod\\limits_{i=1}^{n}R_{Z_iZ_{i+1}}(\\frac{t}{T}x_{i})R_{Y_iY_{i+1}}(\\frac{t}{T}x_{i})R_{X_iX_{i+1}}(\\frac{t}{T}x_{i})\\right)^{T}\\bigotimes_{i=1}^{n+1}\\left|\\psi_{i}\\right>,\n",
"$$\n",
"\n",
"这里的 $R_{XX}$、$R_{YY}$ 和 $R_{ZZ}$ 都是 IQP 编码方式中提到的两量子比特旋转门,$T$ 是进行特罗特步骤的次数,$\\left|\\psi_{i}\\right>$ 则是一个哈尔随机(Haar-random)单比特量子态。\n",
"在实际实现的过程中,你可以先准备哈尔随机量子态,然后再加上 $T$ 层 $R_{XX}$、$R_{YY}$、$R_{ZZ}$ 门。"
]
},
{
"cell_type": "markdown",
"id": "585a2e86",
"metadata": {},
"source": [
"---\n",
"\n",
"## 参考文献\n",
"\n",
"[1] Schuld, Maria. \"Quantum machine learning models are kernel methods.\" [arXiv:2101.11020 (2021).](https://arxiv.org/abs/2101.11020)\n",
"\n",
"[2] Havlíček, Vojtěch, et al. \"Supervised learning with quantum-enhanced feature spaces.\" [Nature 567.7747 (2019): 209-212.](https://www.nature.com/articles/s41586-019-0980-2)\n",
"\n",
"[3] Huang, Hsin-Yuan, et al. \"Power of data in quantum machine learning.\" [Nature Communications 12.1 (2021): 1-9.](https://www.nature.com/articles/s41467-021-22539-9)\n",
"\n",
"[4] Cade, Chris, et al. \"Strategies for solving the Fermi-Hubbard model on near-term quantum computers.\" [Physical Review B 102.23 (2020): 235122.](https://journals.aps.org/prb/abstract/10.1103/PhysRevB.102.235122)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
{
"cells": [
{
"cell_type": "markdown",
"id": "2b8d96ea",
"metadata": {},
"source": [
"# Encoding Classical Data into Quantum States\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "f160535c",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>pre { white-space: pre !important; }</style>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.core.display import HTML\n",
"display(HTML(\"<style>pre { white-space: pre !important; }</style>\"))"
]
},
{
"cell_type": "markdown",
"id": "2e2ccb8d",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"Quantum encoding is a process to transform classical information into quantum states. \n",
"It plays a crucial role in using quantum algorithms to solve classical problems, especially in quantum machine learning tasks. Interested readers can find an example of using quantum encoding \n",
"in our tutorial on [quantum classifier](./QClassifier_EN.ipynb), where we use quantum neural networks to accomplish a classical binary classification task.\n",
"Quantum encoding can be seen as a quantum circuit that acts on $\\left| 0^n \\right>$ state (n is the number of qubits), with some parameters determined by the classical information.\n",
"\n",
"In this tutorial, we will discuss five typical encoding schemes, including **basis encoding** [1], **amplitude encoding** [1], **angle encoding** [1], **instantaneous quantum polynomial (IQP) style encoding** [2], and **Hamiltonian evolution ansatz encoding** [3]. In Paddle Quantum, we provide built-in methods for the first four encoding strategies.\n",
"\n",
"## Basis Encoding\n",
"\n",
"Basis encoding is the most intuitive way to encode classical information into a quantum state. It encodes an $n$-bit binary string $x$ to an $n$-qubit quantum state $\\left|x\\right> = \\left|i_x\\right>$, where $\\left|i_x\\right>$ is a computational basis state. For example, if $x=1011$, the corresponding quantum state after basis encoding is $\\left|1011\\right>$. Let's take a look at how to use Paddle Quantum to implement basis encoding:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "3b220934",
"metadata": {},
"outputs": [],
"source": [
"# Import necessary library\n",
"import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"id": "9e653bdf",
"metadata": {},
"source": [
"Start from $\\left| 0^n \\right>$, and we apply an $X$ gate if the corresponding classical bit is 1. We construct the circuit as follows: "
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "ff86f454",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--X--\n",
" \n",
"-----\n",
" \n",
"--X--\n",
" \n",
"--X--\n",
" \n"
]
}
],
"source": [
"# Number of qubits = length of the classical binary string\n",
"n = 4\n",
"# Initialize the circuit\n",
"basis_enc = UAnsatz(n)\n",
"# X is the classical information\n",
"x = '1011'\n",
"# Add a Pauli X gate to the ith qubit if the ith classical bit is 1\n",
"for i in range(len(x)):\n",
" if x[i] == '1':\n",
" basis_enc.x(i)\n",
" \n",
"print(basis_enc)"
]
},
{
"cell_type": "markdown",
"id": "95559773",
"metadata": {},
"source": [
"The corresponding quantum state after basis encoding is: "
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "9a5909db",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j\n",
" 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n"
]
}
],
"source": [
"basis_quan_state = basis_enc.run_state_vector()\n",
"print(basis_quan_state.numpy())"
]
},
{
"cell_type": "markdown",
"id": "a6360824",
"metadata": {},
"source": [
"which is the state $\\left|1011\\right>$ as we desired.\n",
"\n",
"In Paddle Quantum, we also provide a built-in method for basis encoding:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "a7594453",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j\n",
" 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n"
]
}
],
"source": [
"# Built-in basis encoding\n",
"built_in_basis_enc = UAnsatz(n)\n",
"# Classical information x should be of type Tensor\n",
"x = paddle.to_tensor([1, 0, 1, 1])\n",
"built_in_basis_enc.basis_encoding(x)\n",
"built_in_basis_enc_state = built_in_basis_enc.run_state_vector()\n",
"print(built_in_basis_enc_state.numpy())"
]
},
{
"cell_type": "markdown",
"id": "0630a047",
"metadata": {},
"source": [
"## Amplitude Encoding\n",
"\n",
"Amplitude encoding encodes a vector $\\mathbf{x}$ of length $N$ into amplitudes of an $n$-qubit quantum state with $n = \\lceil\\log_2(N)\\rceil$:\n",
"\n",
"$$\n",
"\\begin{align*} \\left|\\mathbf{x}\\right> = \\sum\\limits_{i}^{N}x_i\\left|i\\right>\\end{align*},\n",
"$$\n",
"\n",
"where $\\left\\{\\left|i\\right>\\right\\}$ is the computational basis for the Hilbert space. Since the classical information forms the amplitudes of a quantum state, the input needs to satisfy the normalization condition: $\\left|\\mathbf{x}\\right|^{2} = 1$.\n",
"\n",
"For instance, if $\\mathbf{x} = \\begin{bmatrix} \\frac{1}{2}\\\\ \\frac{1}{2}\\\\ -\\frac{1}{2}\\\\ -\\frac{1}{2} \\end{bmatrix}$, the corresponding quantum state will be $\\left|\\mathbf{x}\\right> = \\frac{1}{2}\\left|00\\right> + \\frac{1}{2} \\left|01\\right> - \\frac{1}{2} \\left|10\\right> - \\frac{1}{2} \\left|11\\right>$. \n",
"Here is another example with $N < 2^n$, if $\\mathbf{y} = \\begin{bmatrix} \\frac{1}{\\sqrt{3}}\\\\\\frac{1}{\\sqrt{3}}\\\\\\frac{1}{\\sqrt{3}} \\end{bmatrix}$, the corresponding quantum state will be $\\left|\\mathbf{y}\\right> = \\frac{1}{\\sqrt{3}}\\left|00\\right> + \\frac{1}{\\sqrt{3}}\\left|01\\right> + \\frac{1}{\\sqrt{3}}\\left|10\\right>$.\n",
"\n",
"You may have already noticed, amplitude encoding cannot be represented as a trivial quantum circuit. Instead, it can be implemented using arbitrary state preparation [1]. But don't worry. In Paddle Quantum, we provide a built-in method for amplitude encoding:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "adb251b5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0.57735026+0.j 0.57735026+0.j 0.57735026+0.j 0. +0.j]\n"
]
}
],
"source": [
"# Built-in amplitude encoding\n",
"# Number of qubits = 2\n",
"n = 2\n",
"# Initialize the circuit\n",
"built_in_amplitude_enc = UAnsatz(n)\n",
"# Classical information x should be of type Tensor\n",
"x = paddle.to_tensor([0.5, 0.5, 0.5])\n",
"state = built_in_amplitude_enc.amplitude_encoding(x, 'state_vector')\n",
"print(state.numpy())"
]
},
{
"cell_type": "markdown",
"id": "a90d9ca6",
"metadata": {},
"source": [
"In Paddle Quantum, we will normalize the input classical vector by default. As you can see, \n",
"the result is indeed $\\frac{1}{\\sqrt{3}}\\left|00\\right> + \\frac{1}{\\sqrt{3}}\\left|01\\right> + \\frac{1}{\\sqrt{3}}\\left|10\\right>$.\n",
"\n",
"## Angle Encoding\n",
"\n",
"Angle encoding makes use of rotation gates to encode classical information $\\mathbf{x}$. The classical information determines angles of rotation gates:\n",
"\n",
"$$\n",
"\\left|\\mathbf{x}\\right> = \\bigotimes_{i}^{n} R(\\mathbf{x}_i) \\left| 0^n \\right>,\n",
"$$\n",
"\n",
"where $R$ can be one of $R_x$, $R_y$, $R_z$. Usually, the number of qubits used for encoding is equal to the dimension of vector $\\mathbf{x}$. \n",
"For example, when $\\mathbf{x} = \\begin{bmatrix} \\pi \\\\ \\pi\\\\ \\pi \\end{bmatrix}$, angle encoding rotates every qubit around Y-axis (if we choose $R_y$) for degree $\\pi$, so that the corresponding quantum state will be $\\left|111\\right>$.\n",
"\n",
"The circuit for angle encoding can be constructed as follows: "
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "5f9c513e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--Ry(3.142)--\n",
" \n",
"--Ry(3.142)--\n",
" \n",
"--Ry(3.142)--\n",
" \n"
]
}
],
"source": [
"# Number of qubits = length of the classical information\n",
"n = 3\n",
"# Initialize the circuit\n",
"angle_enc = UAnsatz(n)\n",
"# X is the classical information\n",
"x = paddle.to_tensor([np.pi, np.pi, np.pi], 'float64')\n",
"# Add a layer of rotation y gates\n",
"for i in range(len(x)):\n",
" angle_enc.ry(x[i], i)\n",
" \n",
"print(angle_enc)"
]
},
{
"cell_type": "markdown",
"id": "1e5a6e06",
"metadata": {},
"source": [
"The corresponding quantum state after amplitude encoding is:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "295e7c3d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0j, 0j, 0j, 0j, 0j, 0j, 0j, (1+0j)]\n"
]
}
],
"source": [
"angle_quan_state = angle_enc.run_state_vector()\n",
"print([np.round(i, 2) for i in angle_quan_state.numpy()])"
]
},
{
"cell_type": "markdown",
"id": "c13e7bf8",
"metadata": {},
"source": [
"The corresponding state is $\\left|111\\right>$ as we desired.\n",
"\n",
"In Paddle Quantum, we also provide a built-in method for angle encoding:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "af779e74",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0j, 0j, 0j, 0j, 0j, 0j, 0j, (1+0j)]\n"
]
}
],
"source": [
"# Built-in angle encoding\n",
"# Number of qubits\n",
"n = 3\n",
"# Initialize the circuit\n",
"built_in_angle_enc = UAnsatz(n)\n",
"# Classical information x should be of type Tensor\n",
"x = paddle.to_tensor([np.pi, np.pi, np.pi], 'float64')\n",
"built_in_angle_enc.angle_encoding(x, \"ry\")\n",
"state = built_in_angle_enc.run_state_vector()\n",
"print([np.round(i, 2) for i in state.numpy()])"
]
},
{
"cell_type": "markdown",
"id": "94d09e5f",
"metadata": {},
"source": [
"## IQP Style Encoding\n",
"\n",
"IQP style encoding is a relatively complicated encoding strategy. We encode classical information $\\mathbf{x}$ to \n",
"\n",
"$$\n",
"\\left|\\mathbf{x}\\right> = \\left(\\mathrm{U}_\\mathrm{Z}(\\mathbf{x})\\mathrm{H}^{\\otimes n}\\right)^{r}\\left|0^n\\right>,\n",
"$$\n",
"\n",
"where $r$ is the depth of the circuit, indicating the repeating times of $\\mathrm{U}_\\mathrm{Z}(\\mathbf{x})\\mathrm{H}^{\\otimes n}$. $\\mathrm{H}^{\\otimes n}$ is a layer of Hadamard gates acting on all qubits. $\\mathrm{U}_\\mathrm{Z}(\\mathbf{x})$ is the key step in IQP encoding scheme:\n",
"\n",
"$$\n",
"\\mathrm{U}_\\mathrm{Z}(\\mathbf{x})=\\prod\\limits_{[i,j]\\in S}R_{Z_iZ_j}(x_ix_j)\\bigotimes_{k=1}^{n} R_z(x_k),\n",
"$$\n",
"\n",
"where $S$ is the set containing all pairs of qubits to be entangled using $R_{ZZ}$ gates.\n",
"\n",
"First, we consider a simple two-qubit gate: $R_{Z_1Z_2}(\\theta)$. Its mathematical form $e^{-i\\frac{\\theta}{2}Z_1\\otimes Z_2}$ can be seen as a two-qubit rotation gate around ZZ , which makes these two qubits entangled. \n",
"One can implement this gate using Paddle Quantum as follows:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "bcde1189",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--*-----------------*--\n",
" | | \n",
"--X----Rz(2.000)----X--\n",
" \n"
]
}
],
"source": [
"# Number of qubits\n",
"n = 2\n",
"# Initialize the circuit\n",
"Rzz = UAnsatz(n)\n",
"# Theta is the angle of Rzz gate\n",
"theta = paddle.to_tensor([2], 'float64')\n",
"# Implement Rzz gate\n",
"Rzz.cnot([0, 1])\n",
"Rzz.rz(theta, 1)\n",
"Rzz.cnot([0, 1])\n",
" \n",
"print(Rzz)"
]
},
{
"cell_type": "markdown",
"id": "89c92df4",
"metadata": {},
"source": [
"In $\\mathrm{U}_\\mathrm{Z}$, an $R_{ZZ}$ gate needs to be added between every pair of qubits in set $S$. In our built-in IQP encoding method, users are allowed to define their customized set $S$.\n",
"\n",
"Now, let's take a look at how to implement IQP encoding using Paddle Quantum:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "38f5afac",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--H----Rz(-1.45)----*-----------------*------------------------------------------------\n",
" | | \n",
"--H----Rz(3.000)----X----Rz(-4.35)----X----*-----------------*-------------------------\n",
" | | \n",
"--H----Rz(2.000)---------------------------X----Rz(6.000)----X----*-----------------*--\n",
" | | \n",
"--H----Rz(-0.05)--------------------------------------------------X----Rz(-0.10)----X--\n",
" \n"
]
}
],
"source": [
"# Number of qubits\n",
"n = 4\n",
"# Initialize the circuit\n",
"iqp_enc = UAnsatz(n)\n",
"# X is the classical information\n",
"x = paddle.to_tensor([-1.45, 3, 2, -0.05], 'float64')\n",
"# S is a list containing all the pairs to be entagled\n",
"S = [[0, 1], [1, 2], [2, 3]]\n",
"# r is the repeating times of U\n",
"r = 1\n",
"\n",
"for i in range(r):\n",
" # Add a layer of hadamard gates\n",
" iqp_enc.superposition_layer()\n",
" # Add a layer of rotation z gates\n",
" for j in range(n):\n",
" iqp_enc.rz(x[j] ,j)\n",
" # Add a layer of ZZ gates\n",
" for k in S:\n",
" iqp_enc.cnot(k)\n",
" iqp_enc.rz(x[k[0]] * x[k[1]], k[1])\n",
" iqp_enc.cnot(k)\n",
" \n",
"print(iqp_enc)"
]
},
{
"cell_type": "markdown",
"id": "a0e60e87",
"metadata": {},
"source": [
"The corresponding quantum state after IQP style encoding is:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "187b7ec4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[(0.25+0j), (0.24719-0.03736j), (-0.0115+0.24974j), (-0.02397+0.24885j), (-0.01559-0.24951j), (-0.0527-0.24438j), (0.21313+0.13067j), (0.20633+0.14116j), (0.22138+0.11615j), (0.23625+0.08176j), (-0.12621+0.2158j), (-0.13684+0.20922j), (0.07483+0.23854j), (0.10964+0.22468j), (-0.2382-0.07589j), (-0.23411-0.0877j)]\n"
]
}
],
"source": [
"iqp_quan_state = iqp_enc.run_state_vector()\n",
"print([np.round(i, 5) for i in iqp_quan_state.numpy()])"
]
},
{
"cell_type": "markdown",
"id": "9aee1dcb",
"metadata": {},
"source": [
"In Paddle Quantum, we provide a built-in IQP encoding method that exactly follows the way we explained above. However, this is just a particular case for IQP style encoding. IQP style encoding can refer \n",
"to a more general class of encoding schemes. For example, you can replace the rotation Z gate with rotation X gate or rotation Y gate and replace $R_{ZZ}$ gate with $R_{XX}$ gate or $R_{YY}$ gate. Besides, you can think of three-qubit rotation gates, and add more layers with these three-qubit rotation gates."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "a81b03cb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[(0.25+0j), (0.24719-0.03736j), (-0.0115+0.24974j), (-0.02397+0.24885j), (-0.01559-0.24951j), (-0.0527-0.24438j), (0.21313+0.13067j), (0.20633+0.14116j), (0.22138+0.11615j), (0.23625+0.08176j), (-0.12621+0.2158j), (-0.13684+0.20922j), (0.07483+0.23854j), (0.10964+0.22468j), (-0.2382-0.07589j), (-0.23411-0.0877j)]\n"
]
}
],
"source": [
"# Built-in IQP style encoding\n",
"# Number of qubits\n",
"n = 4\n",
"# Initialize the circuit\n",
"built_in_iqp_enc = UAnsatz(n)\n",
"# Classical information x should be of type Tensor\n",
"x = paddle.to_tensor([-1.45, 3, 2, -0.05], 'float64')\n",
"# S is a list containing all the pairs to be entagled\n",
"S = [[0, 1], [1, 2], [2, 3]]\n",
"# r is the repeating times of U\n",
"r = 1\n",
"built_in_iqp_enc.iqp_encoding(x, r, S)\n",
"built_in_iqp_enc_state = built_in_iqp_enc.run_state_vector()\n",
"print([np.round(i, 5) for i in built_in_iqp_enc_state.numpy()])"
]
},
{
"cell_type": "markdown",
"id": "251975b7",
"metadata": {},
"source": [
"## Hamiltonian Evolution Ansatz Encoding\n",
"\n",
"Hamiltonian evolution ansatz encoding, which uses a Trotter formula to approximate an evolution, has been explored in obtaining the ground state of a Hubbard model [4].\n",
"\n",
"$$\n",
"\\left|\\mathbf{x}\\right> = \\left(\\prod\\limits_{i=1}^{n}R_{Z_iZ_{i+1}}(\\frac{t}{T}x_{i})R_{Y_iY_{i+1}}(\\frac{t}{T}x_{i})R_{X_iX_{i+1}}(\\frac{t}{T}x_{i})\\right)^{T}\\bigotimes_{i=1}^{n+1}\\left|\\psi_{i}\\right>,\n",
"$$\n",
"\n",
"where $R_{XX}, R_{YY}, R_{ZZ}$ are the same rotation gates described in IQP style encoding, T is the number of Trotter steps, and $\\left|\\psi_{i}\\right>$ is a Haar-random single-qubit quantum state.\n",
"You can implement this encoding by applying T layers of $R_{XX}, R_{YY}, R_{ZZ}$ gates to the prepared Haar-random quantum state."
]
},
{
"cell_type": "markdown",
"id": "b4dddb79",
"metadata": {},
"source": [
"---\n",
"\n",
"## References\n",
"\n",
"[1] Schuld, Maria. \"Quantum machine learning models are kernel methods.\" [arXiv:2101.11020 (2021).](https://arxiv.org/abs/2101.11020)\n",
"\n",
"[2] Havlíček, Vojtěch, et al. \"Supervised learning with quantum-enhanced feature spaces.\" [Nature 567.7747 (2019): 209-212.](https://www.nature.com/articles/s41586-019-0980-2)\n",
"\n",
"[3] Huang, Hsin-Yuan, et al. \"Power of data in quantum machine learning.\" [Nature Communications 12.1 (2021): 1-9.](https://www.nature.com/articles/s41467-021-22539-9)\n",
"\n",
"[4] Cade, Chris, et al. \"Strategies for solving the Fermi-Hubbard model on near-term quantum computers.\" [Physical Review B 102.23 (2020): 235122.](https://journals.aps.org/prb/abstract/10.1103/PhysRevB.102.235122)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
......@@ -49,8 +49,36 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T09:17:21.098395Z",
"start_time": "2021-01-09T09:17:20.543481Z"
"end_time": "2021-04-30T08:58:04.575047Z",
"start_time": "2021-04-30T08:58:04.555128Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"<style>pre { white-space: pre !important; }</style>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.core.display import HTML\n",
"display(HTML(\"<style>pre { white-space: pre !important; }</style>\"))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-30T08:58:08.278605Z",
"start_time": "2021-04-30T08:58:05.042247Z"
}
},
"outputs": [],
......@@ -76,11 +104,11 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T09:17:37.603403Z",
"start_time": "2021-01-09T09:17:37.590987Z"
"end_time": "2021-04-30T08:58:08.292440Z",
"start_time": "2021-04-30T08:58:08.281478Z"
}
},
"outputs": [],
......@@ -111,11 +139,11 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T09:17:54.275730Z",
"start_time": "2021-01-09T09:17:54.266539Z"
"end_time": "2021-04-30T08:58:08.310082Z",
"start_time": "2021-04-30T08:58:08.303101Z"
}
},
"outputs": [],
......@@ -125,7 +153,6 @@
"block_len = 2 # 每个模组的长度\n",
"theta_size = N*block_len*cir_depth # 网络参数 theta 的大小\n",
"\n",
"\n",
"# 搭建编码器 Encoder E\n",
"def Encoder(theta):\n",
"\n",
......@@ -143,7 +170,7 @@
" cir.cnot([which_qubit, which_qubit + 1])\n",
" cir.cnot([N-1, 0])\n",
"\n",
" return cir.U"
" return cir"
]
},
{
......@@ -164,11 +191,11 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T09:18:38.173148Z",
"start_time": "2021-01-09T09:18:20.214869Z"
"end_time": "2021-04-30T08:58:31.111139Z",
"start_time": "2021-04-30T08:58:20.555305Z"
}
},
"outputs": [
......@@ -185,7 +212,15 @@
"iter: 70 loss: 0.1013 fid: 0.8914\n",
"iter: 80 loss: 0.1012 fid: 0.8917\n",
"iter: 90 loss: 0.1010 fid: 0.8921\n",
"iter: 100 loss: 0.1008 fid: 0.8924\n"
"iter: 100 loss: 0.1008 fid: 0.8924\n",
"\n",
"训练后的电路:\n",
"--Ry(3.935)----Rz(2.876)----*---------X----Ry(2.678)----Rz(6.372)----*---------X----Ry(5.516)----Rz(4.082)----*---------X----Ry(1.199)----Rz(1.584)----*---------X----Ry(4.512)----Rz(0.847)----*---------X----Ry(5.038)----Rz(0.564)----*---------X--\n",
" | | | | | | | | | | | | \n",
"--Ry(2.045)----Rz(4.282)----X----*----|----Ry(6.116)----Rz(6.203)----X----*----|----Ry(5.135)----Rz(4.828)----X----*----|----Ry(3.532)----Rz(3.827)----X----*----|----Ry(0.497)----Rz(1.693)----X----*----|----Ry(5.243)----Rz(5.329)----X----*----|--\n",
" | | | | | | | | | | | | \n",
"--Ry(2.706)----Rz(4.168)---------X----*----Ry(2.141)----Rz(2.014)---------X----*----Ry(5.364)----Rz(-0.34)---------X----*----Ry(4.014)----Rz(2.668)---------X----*----Ry(3.419)----Rz(1.952)---------X----*----Ry(4.255)----Rz(1.856)---------X----*--\n",
" \n"
]
}
],
......@@ -214,7 +249,8 @@
" def forward(self):\n",
" \n",
" # 生成初始的编码器 E 和解码器 D\n",
" E = Encoder(self.theta)\n",
" cir = Encoder(self.theta)\n",
" E = cir.U\n",
" E_dagger = dagger(E)\n",
" D = E_dagger\n",
" D_dagger = E\n",
......@@ -234,7 +270,7 @@
" zero_Hamiltonian = paddle.to_tensor(np.diag([1,0]).astype('complex128'))\n",
" loss = 1 - real(trace(matmul(zero_Hamiltonian, rho_trash)))\n",
"\n",
" return loss, self.rho_in, rho_out\n",
" return loss, self.rho_in, rho_out, cir\n",
"\n",
"\n",
"paddle.seed(SEED)\n",
......@@ -247,7 +283,7 @@
"# 优化循环\n",
"for itr in range(1, ITR + 1):\n",
" # 前向传播计算损失函数\n",
" loss, rho_in, rho_out = net()\n",
" loss, rho_in, rho_out, cir = net()\n",
" # 反向传播极小化损失函数\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
......@@ -255,7 +291,10 @@
" # 计算并打印保真度\n",
" fid = state_fidelity(rho_in.numpy(), rho_out.numpy())\n",
" if itr % 10 == 0:\n",
" print('iter:', itr, 'loss:', '%.4f' % loss, 'fid:', '%.4f' % np.square(fid))"
" print('iter:', itr, 'loss:', '%.4f' % loss, 'fid:', '%.4f' % np.square(fid))\n",
" if itr == ITR:\n",
" print(\"\\n训练后的电路:\") \n",
" print(cir)"
]
},
{
......
......@@ -49,8 +49,36 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T09:12:23.184162Z",
"start_time": "2021-01-09T09:12:22.345158Z"
"end_time": "2021-04-30T08:57:25.375761Z",
"start_time": "2021-04-30T08:57:25.355799Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"<style>pre { white-space: pre !important; }</style>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.core.display import HTML\n",
"display(HTML(\"<style>pre { white-space: pre !important; }</style>\"))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-30T08:57:29.266507Z",
"start_time": "2021-04-30T08:57:25.894969Z"
}
},
"outputs": [],
......@@ -77,11 +105,11 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T09:12:38.828744Z",
"start_time": "2021-01-09T09:12:38.798795Z"
"end_time": "2021-04-30T08:57:29.283394Z",
"start_time": "2021-04-30T08:57:29.270542Z"
}
},
"outputs": [],
......@@ -111,11 +139,11 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T09:12:57.894565Z",
"start_time": "2021-01-09T09:12:57.866300Z"
"end_time": "2021-04-30T08:57:29.301622Z",
"start_time": "2021-04-30T08:57:29.288113Z"
}
},
"outputs": [],
......@@ -143,7 +171,7 @@
" cir.cnot([which_qubit, which_qubit + 1])\n",
" cir.cnot([N-1, 0])\n",
"\n",
" return cir.U"
" return cir"
]
},
{
......@@ -164,11 +192,11 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T09:15:02.004745Z",
"start_time": "2021-01-09T09:14:42.039212Z"
"end_time": "2021-04-30T08:57:52.962725Z",
"start_time": "2021-04-30T08:57:42.476996Z"
}
},
"outputs": [
......@@ -185,7 +213,15 @@
"iter: 70 loss: 0.1013 fid: 0.8914\n",
"iter: 80 loss: 0.1012 fid: 0.8917\n",
"iter: 90 loss: 0.1010 fid: 0.8921\n",
"iter: 100 loss: 0.1008 fid: 0.8924\n"
"iter: 100 loss: 0.1008 fid: 0.8924\n",
"\n",
"The trained circuit:\n",
"--Ry(3.935)----Rz(2.876)----*---------X----Ry(2.678)----Rz(6.372)----*---------X----Ry(5.516)----Rz(4.082)----*---------X----Ry(1.199)----Rz(1.584)----*---------X----Ry(4.512)----Rz(0.847)----*---------X----Ry(5.038)----Rz(0.564)----*---------X--\n",
" | | | | | | | | | | | | \n",
"--Ry(2.045)----Rz(4.282)----X----*----|----Ry(6.116)----Rz(6.203)----X----*----|----Ry(5.135)----Rz(4.828)----X----*----|----Ry(3.532)----Rz(3.827)----X----*----|----Ry(0.497)----Rz(1.693)----X----*----|----Ry(5.243)----Rz(5.329)----X----*----|--\n",
" | | | | | | | | | | | | \n",
"--Ry(2.706)----Rz(4.168)---------X----*----Ry(2.141)----Rz(2.014)---------X----*----Ry(5.364)----Rz(-0.34)---------X----*----Ry(4.014)----Rz(2.668)---------X----*----Ry(3.419)----Rz(1.952)---------X----*----Ry(4.255)----Rz(1.856)---------X----*--\n",
" \n"
]
}
],
......@@ -213,7 +249,8 @@
" def forward(self):\n",
" \n",
" # Generate initial encoder E and decoder D\n",
" E = Encoder(self.theta)\n",
" cir = Encoder(self.theta)\n",
" E = cir.U\n",
" E_dagger = dagger(E)\n",
" D = E_dagger\n",
" D_dagger = E\n",
......@@ -233,7 +270,7 @@
" zero_Hamiltonian = paddle.to_tensor(np.diag([1,0]).astype('complex128'))\n",
" loss = 1 - real(trace(matmul(zero_Hamiltonian, rho_trash)))\n",
"\n",
" return loss, self.rho_in, rho_out\n",
" return loss, self.rho_in, rho_out, cir\n",
"\n",
"\n",
"paddle.seed(SEED)\n",
......@@ -246,7 +283,7 @@
"# Optimization loops\n",
"for itr in range(1, ITR + 1):\n",
" # Forward propagation for calculating loss function\n",
" loss, rho_in, rho_out = net()\n",
" loss, rho_in, rho_out, cir = net()\n",
" # Use back propagation to minimize the loss function\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
......@@ -254,7 +291,10 @@
" # Calculate and print fidelity\n",
" fid = state_fidelity(rho_in.numpy(), rho_out.numpy())\n",
" if itr% 10 == 0:\n",
" print('iter:', itr,'loss:','%.4f'% loss,'fid:','%.4f'% np.square(fid))"
" print('iter:', itr,'loss:','%.4f'% loss,'fid:','%.4f'% np.square(fid))\n",
" if itr == ITR:\n",
" print(\"\\nThe trained circuit:\")\n",
" print(cir)"
]
},
{
......
......@@ -40,7 +40,7 @@
"\n",
"这里我们给出实现量子电路学习 (QCL) 框架下量子分类器的一个流程。\n",
"\n",
"1. 在初始化的量子比特 $\\lvert 0 \\rangle$ 上作用参数化的酉门 $U$(Unitary Gate),从而把原始的经典数据点 $x^k$ 编码成量子计算机可以运行的量子数据 $\\lvert \\psi_{in}\\rangle^k$。\n",
"1. 在初始化的量子比特 $\\lvert 0 \\rangle$ 上作用参数化的酉门 $U$(unitary gate),从而把原始的经典数据点 $x^k$ 编码成量子计算机可以运行的量子数据 $\\lvert \\psi_{in}\\rangle^k$。\n",
"2. 使输入态 $\\lvert \\psi_{in} \\rangle^k$ 通过参数为 $\\theta$ 的参数化电路 $U(\\theta)$ ,由此获得输出态 $\\lvert \\psi_{out}\\rangle^k = U(\\theta)\\lvert \\psi_{in} \\rangle^k$。\n",
"3. 对量子神经网络处理后的量子态 $\\lvert \\psi_{out}\\rangle^k$ 进行测量和数据后处理,得到估计出的标签 $\\tilde{y}^{k}$。\n",
"4. 重复步骤2-3直到数据集内所有的数据点都经过了处理。然后计算损失函数 $\\mathcal{L}(\\theta)$。\n",
......@@ -215,7 +215,7 @@
},
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -234,7 +234,7 @@
},
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -285,7 +285,7 @@
"U(x^{k}) = \\otimes_{j=0}^{m-1} R_j^z\\big[\\arccos(x_{j \\, \\text{mod} \\, 2}\\cdot x_{j \\, \\text{mod} \\, 2})\\big] R_j^y\\big[\\arcsin(x_{j \\, \\text{mod} \\, 2}) \\big],\\tag{2}\n",
"$$\n",
"\n",
"**注意** :这种表示下,我们将第一个量子比特编号为 $j = 0$。更多编码方式见 [Robust data encodings for quantum classifiers](https://arxiv.org/pdf/2003.01695.pdf)。这里我们也欢迎读者自己创新尝试全新的编码方式。\n",
"**注意** :这种表示下,我们将第一个量子比特编号为 $j = 0$。更多编码方式见 [Robust data encodings for quantum classifiers](https://arxiv.org/pdf/2003.01695.pdf)。读者也可以直接使用量桨中提供的[编码方式](./DataEncoding_CN.ipynb)。这里我们也欢迎读者自己创新尝试全新的编码方式。\n",
"由于这种编码的方式看着比较复杂,我们不妨来举一个简单的例子。假设我们给定一个数据点 $x = (x_0, x_1)= (1,0)$, 显然这个数据点的标签应该为 1,对应上图**蓝色**的点。同时数据点对应的2比特量子门 $U(x)$ 是\n",
"\n",
"$$\n",
......@@ -386,8 +386,7 @@
"$$\n",
"(U_1 |0\\rangle)\\otimes (U_2 |0\\rangle) = (U_1 \\otimes U_2) |0\\rangle\\otimes|0\\rangle\n",
"= (U_1 \\otimes U_2) |00\\rangle.\\tag{8}\n",
"$$\n",
"\n"
"$$"
]
},
{
......@@ -557,7 +556,7 @@
" for i in range(n):\n",
" cir.ry(theta[i][d], i)\n",
"\n",
" return cir.U"
" return cir"
]
},
{
......@@ -692,7 +691,7 @@
" dtype=dtype,\n",
" is_bias=False)\n",
"\n",
" # 定义向前传播机制、计算损失函数 和交叉验证正确率\n",
" # 定义前向传播机制、计算损失函数 和交叉验证正确率\n",
" def forward(self, state_in, label):\n",
" \"\"\"\n",
" Args:\n",
......@@ -707,7 +706,8 @@
" label_pp = paddle.to_tensor(label)\n",
"\n",
" # 按照随机初始化的参数 theta \n",
" Utheta = U_theta(self.theta, n=self.n, depth=self.depth)\n",
" cir = U_theta(self.theta, n=self.n, depth=self.depth)\n",
" Utheta = cir.U\n",
" \n",
" # 因为 Utheta是学习到的,我们这里用行向量运算来提速而不会影响训练效果\n",
" state_out = matmul(state_in, Utheta) # 维度 [-1, 1, 2 ** n]\n",
......@@ -723,7 +723,7 @@
" is_correct = (paddle.abs(state_predict - label_pp) < 0.5).nonzero().shape[0]\n",
" acc = is_correct / label.shape[0]\n",
"\n",
" return loss, acc, state_predict.numpy()"
" return loss, acc, state_predict.numpy(), cir"
]
},
{
......@@ -760,7 +760,7 @@
" # 计算预测: heat_data\n",
" input_state_test = paddle.to_tensor(\n",
" datapoints_transform_to_state(x_y_, N))\n",
" loss_useless, acc_useless, state_predict = net(state_in=input_state_test, label=x_y_[:, 0])\n",
" loss_useless, acc_useless, state_predict, cir = net(state_in=input_state_test, label=x_y_[:, 0])\n",
" heat_data = state_predict.reshape(Num_points, Num_points)\n",
"\n",
" # 画图\n",
......@@ -805,22 +805,24 @@
" input_state = paddle.to_tensor(datapoints_transform_to_state(train_x[itr * BATCH:(itr + 1) * BATCH], N))\n",
"\n",
" # 前向传播计算损失函数\n",
" loss, train_acc, state_predict_useless \\\n",
" loss, train_acc, state_predict_useless, cir \\\n",
" = net(state_in=input_state, label=train_y[itr * BATCH:(itr + 1) * BATCH])\n",
" if itr % 50 == 0:\n",
"\n",
" # 计算测试集上的正确率 test_acc\n",
" input_state_test = paddle.to_tensor(datapoints_transform_to_state(test_x, N))\n",
" loss_useless, test_acc, state_predict_useless \\\n",
" loss_useless, test_acc, state_predict_useless, t_cir \\\n",
" = net(state_in=input_state_test,label=test_y)\n",
" print(\"epoch:\", ep, \"iter:\", itr,\n",
" \"loss: %.4f\" % loss.numpy(),\n",
" \"train acc: %.4f\" % train_acc,\n",
" \"test acc: %.4f\" % test_acc)\n",
"\n",
" # 存储正确率 acc 等信息\n",
" summary_iter.append(itr + ep * N_train)\n",
" summary_test_acc.append(test_acc)\n",
" summary_test_acc.append(test_acc) \n",
" if (itr + 1) % 151 == 0 and ep == EPOCH - 1:\n",
" print(\"训练后的电路:\")\n",
" print(cir)\n",
"\n",
" # 反向传播极小化损失函数\n",
" loss.backward()\n",
......@@ -872,12 +874,21 @@
"epoch: 3 iter: 0 loss: 0.1658 train acc: 1.0000 test acc: 1.0000\n",
"epoch: 3 iter: 50 loss: 0.1359 train acc: 1.0000 test acc: 1.0000\n",
"epoch: 3 iter: 100 loss: 0.0671 train acc: 1.0000 test acc: 1.0000\n",
"epoch: 3 iter: 150 loss: 0.0849 train acc: 1.0000 test acc: 1.0000\n"
"epoch: 3 iter: 150 loss: 0.0849 train acc: 1.0000 test acc: 1.0000\n",
"训练后的电路:\n",
"--Rz(0.542)----Ry(3.456)----Rz(2.699)----*--------------X----Ry(6.153)--\n",
" | | \n",
"--Rz(3.514)----Ry(1.543)----Rz(2.499)----X----*---------|----Ry(3.050)--\n",
" | | \n",
"--Rz(5.947)----Ry(3.161)----Rz(3.897)---------X----*----|----Ry(1.583)--\n",
" | | \n",
"--Rz(0.718)----Ry(5.038)----Rz(1.348)--------------X----*----Ry(0.030)--\n",
" \n"
]
},
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 2 Axes>"
]
......@@ -891,7 +902,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"主程序段总共运行了 30.048875331878662 秒\n"
"主程序段总共运行了 35.94043445587158 秒\n"
]
}
],
......@@ -960,7 +971,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
......
......@@ -202,7 +202,7 @@
},
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -221,7 +221,7 @@
},
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -269,7 +269,7 @@
"\\tag{2}\n",
"$$\n",
"\n",
"**Note:** In this representation, we count the first qubit as $j = 0$. For more encoding methods, see [Robust data encodings for quantum classifiers](https://arxiv.org/pdf/2003.01695.pdf). Here we also encourage readers to try new encoding methods by themselves!\n",
"**Note:** In this representation, we count the first qubit as $j = 0$. For more encoding methods, see [Robust data encodings for quantum classifiers](https://arxiv.org/pdf/2003.01695.pdf). We also provide several built-in [encoding methods](./DataEncoding_EN.ipynb) in Paddle Quantum. Here we also encourage readers to try new encoding methods by themselves!\n",
"\n",
"Since this encoding method looks quite complicated, we might as well give a simple example. Suppose we are given a data point $x = (x_0, x_1)= (1,0)$. The label of this data point should be 1, corresponding to the **blue** point in the figure above. At the same time, the 2-qubit quantum gate $U(x)$ corresponding to the data point is,\n",
"\n",
......@@ -546,7 +546,7 @@
" for i in range(n):\n",
" cir.ry(theta[i][d], i)\n",
"\n",
" return cir.U"
" return cir"
]
},
{
......@@ -698,7 +698,8 @@
" label_pp = paddle.to_tensor(label)\n",
"\n",
" # According to the randomly initialized parameters theta to build the quantum gate\n",
" Utheta = U_theta(self.theta, n=self.n, depth=self.depth)\n",
" cir = U_theta(self.theta, n=self.n, depth=self.depth)\n",
" Utheta = cir.U\n",
" \n",
" # Because Utheta is achieved by learning, we compute with row vectors to speed up without affecting the training effect\n",
" state_out = matmul(state_in, Utheta) # dimension [-1, 1, 2 ** n]\n",
......@@ -714,7 +715,7 @@
" is_correct = (paddle.abs(state_predict - label_pp) < 0.5).nonzero().shape[0]\n",
" acc = is_correct / label.shape[0]\n",
"\n",
" return loss, acc, state_predict.numpy()"
" return loss, acc, state_predict.numpy(), cir"
]
},
{
......@@ -751,7 +752,7 @@
" # make prediction: heat_data\n",
" input_state_test = paddle.to_tensor(\n",
" datapoints_transform_to_state(x_y_, N))\n",
" loss_useless, acc_useless, state_predict = net(state_in=input_state_test, label=x_y_[:, 0])\n",
" loss_useless, acc_useless, state_predict, cir = net(state_in=input_state_test, label=x_y_[:, 0])\n",
" heat_data = state_predict.reshape(Num_points, Num_points)\n",
"\n",
" # plot\n",
......@@ -797,12 +798,12 @@
" input_state = paddle.to_tensor(datapoints_transform_to_state(train_x[itr * BATCH:(itr + 1) * BATCH], N))\n",
"\n",
" # Run forward propagation to calculate loss function\n",
" loss, train_acc, state_predict_useless \\\n",
" loss, train_acc, state_predict_useless, cir \\\n",
" = net(state_in=input_state, label=train_y[itr * BATCH:(itr + 1) * BATCH])\n",
" if itr % 50 == 0:\n",
" # Calculate the correct rate on the test set test_acc\n",
" input_state_test = paddle.to_tensor(datapoints_transform_to_state(test_x, N))\n",
" loss_useless, test_acc, state_predict_useless \\\n",
" loss_useless, test_acc, state_predict_useless, t_cir \\\n",
" = net(state_in=input_state_test,label=test_y)\n",
" print(\"epoch:\", ep, \"iter:\", itr,\n",
" \"loss: %.4f\" % loss.numpy(),\n",
......@@ -812,6 +813,9 @@
" # Store accuracy rate and other information\n",
" summary_iter.append(itr + ep * N_train)\n",
" summary_test_acc.append(test_acc)\n",
" if (itr + 1) % 151 == 0 and ep == EPOCH - 1:\n",
" print(\"The trained circuit:\")\n",
" print(cir)\n",
"\n",
" # Run back propagation to minimize the loss function\n",
" loss.backward()\n",
......@@ -856,12 +860,21 @@
"epoch: 3 iter: 0 loss: 0.1658 train acc: 1.0000 test acc: 1.0000\n",
"epoch: 3 iter: 50 loss: 0.1359 train acc: 1.0000 test acc: 1.0000\n",
"epoch: 3 iter: 100 loss: 0.0671 train acc: 1.0000 test acc: 1.0000\n",
"epoch: 3 iter: 150 loss: 0.0849 train acc: 1.0000 test acc: 1.0000\n"
"epoch: 3 iter: 150 loss: 0.0849 train acc: 1.0000 test acc: 1.0000\n",
"The trained circuit:\n",
"--Rz(0.542)----Ry(3.456)----Rz(2.699)----*--------------X----Ry(6.153)--\n",
" | | \n",
"--Rz(3.514)----Ry(1.543)----Rz(2.499)----X----*---------|----Ry(3.050)--\n",
" | | \n",
"--Rz(5.947)----Ry(3.161)----Rz(3.897)---------X----*----|----Ry(1.583)--\n",
" | | \n",
"--Rz(0.718)----Ry(5.038)----Rz(1.348)--------------X----*----Ry(0.030)--\n",
" \n"
]
},
{
"data": {
"image/png": "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\n",
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 2 Axes>"
]
......@@ -875,7 +888,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"The main program finished running in 39.81194067001343 seconds.\n"
"The main program finished running in 35.49316954612732 seconds.\n"
]
}
],
......@@ -944,7 +957,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......
......@@ -32,7 +32,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"生成对抗网络(Generative Adversarial Network, GAN)是生成模型的一种,是深度学习在近些年中一个重要的发展[1]。它分为两个部分:生成器 $G$(Generator)和判别器 $D$ (Discriminator)。生成器接受随机的噪声信号,以此为输入来生成我们期望得到的数据。判别器判断接收到的数据是不是来自真实数据,通常输出一个 $P(x)$,表示输入数据 $x$ 是真实数据的概率。"
"生成对抗网络(generative adversarial network, GAN)是生成模型的一种,是深度学习在近些年中一个重要的发展[1]。它分为两个部分:生成器 $G$(generator)和判别器 $D$ (discriminator)。生成器接受随机的噪声信号,以此为输入来生成我们期望得到的数据。判别器判断接收到的数据是不是来自真实数据,通常输出一个 $P(x)$,表示输入数据 $x$ 是真实数据的概率。"
]
},
{
......@@ -48,7 +48,7 @@
"source": [
"在这里,我们用纳什均衡的思想来探讨 GAN 的收敛问题。\n",
"\n",
"纳什均衡(Nash equilibrium)是指在包含两个或以上参与者的非合作博弈(Non-cooperative game)中,假设每个参与者都知道其他参与者的均衡策略的情况下,没有参与者可以通过改变自身策略使自身受益时的一个概念解。在博弈论中,如果每个参与者都选择了自己的策略,并且没有玩家可以通过改变策略而其他参与者保持不变而获益,那么当前的策略选择的集合及其相应的结果构成了纳什均衡。\n",
"纳什均衡(Nash equilibrium)是指在包含两个或以上参与者的非合作博弈(non-cooperative game)中,假设每个参与者都知道其他参与者的均衡策略的情况下,没有参与者可以通过改变自身策略使自身受益时的一个概念解。在博弈论中,如果每个参与者都选择了自己的策略,并且没有玩家可以通过改变策略而其他参与者保持不变而获益,那么当前的策略选择的集合及其相应的结果构成了纳什均衡。\n",
"\n",
"我们可以把GAN的训练过程视为生成器和判别器的博弈过程。在这个博弈过程中,无论生成器的策略是什么,判别器最好的策略就是尽量判别出真实数据和生成数据。而无论判别器的策略是什么,生成器最好的策略就是使判别器无法判别出来。我们不难发现,这种博弈是零和博弈(一种非合作博弈),即一方有所得则另一方必有所失。因此生成器和判别器的博弈存在这种纳什均衡策略。而当真实数据的样本足够多,双方的学习能力足够强时,最终就会达到一种纳什均衡点。**生成器具备了生成真实数据的能力,而判别器也无法再区分生成数据和真实数据。**"
]
......@@ -594,7 +594,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.7.0"
},
"toc": {
"base_numbering": 1,
......
{
"cells": [
{
"cell_type": "markdown",
"id": "instructional-length",
"metadata": {},
"source": [
"# 量子核方法\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"id": "desirable-compatibility",
"metadata": {},
"source": [
"## 概览\n",
"\n",
"在量子机器学习中,参数化量子电路(parameterized quantum circuit)扮演着重要的角色。在很多场景中,为了类比经典机器学习领域中的神经网络方法,我们也经常会把参数化量子电路称为量子神经网络。但是实际上,在量子机器学习的相关应用中,人们发现参数化量子电路的数学原理更类似于经典机器学习中的核方法(kernel methods)[1]。这种通过将量子计算和经典核方法相结合的思路以及研究方法,就被称为量子核方法(quantum kernel methods)。这两种方法的结合对于量子计算如何更好的解决一系列机器学习问题提供了全新的视角,因此在近年来收到了极大的关注 [2-7]。在本教程中,我们将探究如何用量子核方法结合支持向量机来实现数据分类。\n",
"\n",
"### 理论背景\n",
"\n",
"在经典机器学习中,核方法一般指的是将低维的数据向量通过特征映射(feature map)映射到高维的特征空间(feature space)中,来识别低维数据中难以分辨的模式的方法。如图1的例子所示,通过将一维的线性不可分数据映射到二维,映射后的数据在二维空间中是线性可分的。\n",
"\n",
"![feature map](./figures/Qkernel-fig-featuremap.png \"图1:核方法中的特征映射\")\n",
"<div style=\"text-align:center\">图1:核方法中的特征映射 </div>\n",
"\n",
"不过,在实际应用中,由于特征空间的维数可能会十分巨大,我们往往并不希望直接对映射后的特征向量进行分析。相反,通过核方法中的另一个核心概念-核函数(kernel function),我们可以隐式地引入特征映射在模式识别上的优势。核函数的定义为数据向量在特征空间里的内积,其具体形式为\n",
"\n",
"$$\n",
"K(\\mathbf{x}_i, \\mathbf{x}_j) = \\phi(\\mathbf{x}_j)^T \\phi(\\mathbf{x}_i),\n",
"\\tag{1}\n",
"$$\n",
"\n",
"其中 $\\phi()$ 就代表着特征映射。需要注意的是,在核方法中我们并不需要显式地写出特征映射,而只需要定义核函数的形式即可。\n",
"\n",
"在经典机器学习中,核方法最具代表性的应用就是支持向量机(support vector machine, SVM)。简单的来说,支持向量机解决的是线性分类问题:以一个二分类的问题举例,我们的数据集为 $T = \\{ (\\mathbf{x}_1, y_1), ..., (\\mathbf{x}_m, y_m) \\} \\subset \\mathcal{X}\\times\\mathbb{Z}_2$,通过一个超平面 $(\\mathbf{w}, b)$,支持向量机可以通过如下决策函数的正负来预测每个数据点 $\\mathbf{x}$ 的标签:\n",
"\n",
"$$\n",
"y_{\\rm pred} = {\\rm sign}(\\langle \\mathbf{w}, \\mathbf{x} \\rangle + b).\n",
"\\tag{2}\n",
"$$\n",
"\n",
"但是对于在原始数据空间中线性不可分的数据而言,这样的做法往往并不可行。所以如图1所示,通过引入我们上文中提到的特征映射,我们可以将原始数据空间中的数据向量映射到特征空间中来进行分类,从而得到更好的分类效果。此时,我们标记特征空间中的超平面为 $(\\mathbf{w}', b')$, 我们的决策函数就变成了:\n",
"\n",
"$$\n",
"y_{\\rm pred} = {\\rm sign}(\\langle \\mathbf{w}', \\phi(\\mathbf{x}) \\rangle + b').\n",
"\\tag{3}\n",
"$$\n",
"\n",
"更进一步的是,我们可以通过对偶化的方法,引入拉格朗日乘子 $\\alpha_i$ 来表示此时的分割超平面 $\\mathbf{w}' = \\sum_i \\alpha_i \\phi(\\mathbf{x_i})$ [8]。此时,我们可以在 $\\alpha_i \\geq 0$,$\\sum_i y_i \\alpha_i=0$ 的约束下,通过最大化\n",
"\n",
"$$\n",
"\\sum_i \\alpha_i - \\frac{1}{2} \\sum_{i, j} \\alpha_i \\alpha_j y_i y_j \\phi(\\mathbf{x}_j)^T \\phi(\\mathbf{x}_i)\n",
"\\tag{4}\n",
"$$\n",
"\n",
"来计算最优参数 $\\alpha_i^*$。不难发现,此时我们只需要计算数据向量在特征空间里的内积 $\\phi(\\mathbf{x}_j)^T \\phi(\\mathbf{x}_i) = K(x_i, x_j)$,正是我们上文中提到的核函数。换言之,在支持向量机中,我们不需要显式地知道特征映射的形式,而只需要计算原始数据在特征空间里的内积,就可以实现在特征空间中对数据进行分类。并且,对于任何新的数据向量 $\\mathbf{x}'$,我们只需要通过核函数 $K(,)$ 计算\n",
"\n",
"$$\n",
"y_{\\rm pred} = {\\rm sign}(\\sum_i \\alpha^*_i \\langle \\phi(\\mathbf{x_i}), \\phi(\\mathbf{x}' \\rangle + b') = \n",
"{\\rm sign}(\\sum_i \\alpha^*_i K(\\mathbf{x}_i, \\mathbf{x}') + b'),\n",
"\\tag{5}\n",
"$$\n",
"\n",
"就可以对数据的标签进行预测。\n",
"\n",
"借助这种思想,我们就可以很简单的理解量子核方法的内涵。首先,我们引入量子特征空间的概念,即我们认为我们通过一个编码电路 $U(\\mathbf{x}) $ 将经典数据向量 $\\mathbf{x} $ 编码到某个量子态 $| \\phi(\\mathbf{x}) \\rangle$ 上:\n",
"\n",
"$$\n",
"U(\\mathbf{x}) | 0^{\\otimes N} \\rangle = | \\phi(\\mathbf{x}) \\rangle.\n",
"\\tag{6}\n",
"$$ \n",
"\n",
"关于编码电路的具体形式我们这里不做展开,感兴趣的读者可以阅读我们的[编码教程](./DataEncoding_CN.ipynb)来了解不同的量子编码电路形式。此时我们的量子特征映射就是从经典数据空间到量子态所处的希尔伯特空间的一种特殊特征映射。在这个基础上,我们将量子核函数(quantum kernel function)定义为经典数据向量在量子特征空间的内积,其具体形式就为\n",
"\n",
"$$\n",
"K^Q_{ij} = |\\langle \\phi(\\mathbf{x}_j) | \\phi(\\mathbf{x}_i) \\rangle |^2,\n",
"\\tag{7}\n",
"$$\n",
"\n",
"上式可以进一步写为\n",
"\n",
"$$\n",
"|\\langle \\phi(\\mathbf{x}_j) | \\phi(\\mathbf{x}_i) \\rangle |^2 = |\\langle 0^{\\otimes N} | U^\\dagger(\\mathbf{x}_j) U(\\mathbf{x}_i) | 0^{\\otimes N} \\rangle |^2.\n",
"\\tag{8}\n",
"$$\n",
"\n",
"不难发现,通过运行如图2中所示的量子电路,并在统计其测量结果为 $| 0^{\\otimes N} \\rangle $ 的概率,我们就可以估计式(8)中的量子核函数。这种方法也被称为量子核估计(quantum kernel estimation, QKE)方法。也就是说,如果我们通过量子核估计方法来计算式(4-5) 中的核函数的话,我们就可以利用支持向量机的方法在量子特征空间来完成数据分类。借助量子特征映射的量子性,人们希望这种量子核方法可以更好地分类具有复杂模式的数据。人们已经证明,通过精心设计量子特征映射,量子核方法就可以用来分辨任何经典方法都无法识别的数据模式 [3]。\n",
"\n",
"![QKE](./figures/Qkernel-fig-QKE.png \"图2:量子核估计电路\")\n",
"<div style=\"text-align:center\">图2:量子核估计电路 </div>\n",
"\n",
"![illustration](./figures/Qkernel-fig-illustrationCN.png \"图3:经典核方法和量子核方法的对比示意图\")\n",
"<div style=\"text-align:center\">图3:经典核方法和量子核方法的对比示意图 </div>"
]
},
{
"cell_type": "markdown",
"id": "willing-shopping",
"metadata": {},
"source": [
"### 拓展:量子机器学习和核方法的联系\n",
"\n",
"在量子机器学习中,往往我们量子电路中的一部分需要将经典的数据编码到其对应的量子态上,其数学形式为:\n",
"\n",
"$$\n",
"| \\phi(x) \\rangle = U (x) | 0^{\\otimes N} \\rangle,\n",
"\\tag{9}\n",
"$$\n",
"\n",
"其中 $U(x)$ 是一个取决于经典数据 $x$ 的参数化电路。正如我们上文中提到的,这种编码的过程可以被考虑成是一种从经典数据空间到量子特征空间的特殊特征映射。同时,考虑一个作用在编码量子态上的量子神经网络电路,其数学形式为:\n",
"\n",
"$$\n",
"| \\psi \\rangle = U_{\\rm QNN}(\\theta)U (\\mathbf{x}) | 0^{\\otimes N} \\rangle,\n",
"\\tag{10}\n",
"$$\n",
"\n",
"其中 $U_{\\rm QNN}(\\theta)$ 为代表量子神经网络的参数化量子电路,$\\theta$ 为其中的参数。我们在电路的最后进行测量,该测量用 $\\mathcal{M}$ 表示。这时,我们测得的期望值为\n",
"\n",
"$$\n",
"\\langle \\mathcal{M} \\rangle = \\langle \\psi | \\mathcal{M} | \\psi \\rangle = \\langle \\phi(\\mathbf{x}) | U^\\dagger_{\\rm QNN}(\\theta) \\mathcal{M} U_{\\rm QNN}(\\theta)| \\phi(\\mathbf{x}) \\rangle.\n",
"\\tag{11}\n",
"$$\n",
"\n",
"我们不妨将测量写成算符的形式 $| \\sigma \\rangle \\langle \\sigma |$ ,那么式(11)就可以进一步被写为\n",
"\n",
"$$\n",
"\\langle \\phi(\\mathbf{x}) | \\sigma'(\\theta) \\rangle \\langle \\sigma' (\\theta) | \\phi(x) \\rangle = \n",
"|\\langle \\sigma' (\\theta) | \\phi(\\mathbf{x}) \\rangle|^2,\n",
"\\tag{12}\n",
"$$\n",
"\n",
"其中 $| \\sigma'(\\theta) \\rangle = U^\\dagger_{\\rm QNN}(\\theta) | \\sigma \\rangle$。这样的话,我们发现我们这种基于量子神经网络的测量结果也可以被认为是量子特征空间中两个量子特征向量的内积:$|\\langle \\sigma' (\\theta) | \\phi(\\mathbf{x}) \\rangle|^2$。\n",
"而该内积,正是我们前文中提到的量子核函数,只不过其中一个特征向量是由一个参数化的测量所描述的。这也就是我们在本教程的一开始提到,量子神经网络模型的数学形式实际上更接近于经典机器学习中的核方法的原因。"
]
},
{
"cell_type": "markdown",
"id": "tutorial-vocabulary",
"metadata": {},
"source": [
"## 示例:利用量子核方法来解决分类问题\n",
"\n",
"> 本教程需要使用 [`sklearn`](https://scikit-learn.org/stable/install.html) 中的相关函数来实现支持向量机的功能。需要的读者可以运行下面的代码块来安装相关模块:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "informative-miami",
"metadata": {},
"outputs": [],
"source": [
"from IPython.display import clear_output\n",
"\n",
"!pip install scikit-learn\n",
"clear_output()"
]
},
{
"cell_type": "markdown",
"id": "emerging-anxiety",
"metadata": {},
"source": [
"下面,我们用一个简单的例子来展示如何在 Paddle Quantum 中模拟量子核估计电路,并将其应用在一个实际的分类任务上。"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "acting-nursery",
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"import matplotlib\n",
"import numpy as np\n",
"import paddle\n",
"from numpy import pi as PI\n",
"from matplotlib import pyplot as plt\n",
"\n",
"from paddle import matmul, transpose\n",
"from paddle_quantum.circuit import UAnsatz\n",
"\n",
"import sklearn\n",
"from sklearn import svm\n",
"from sklearn.datasets import fetch_openml, make_moons, make_circles\n",
"from sklearn.model_selection import train_test_split\n",
"\n",
"from IPython.display import clear_output\n",
"from tqdm import tqdm"
]
},
{
"cell_type": "markdown",
"id": "fluid-rating",
"metadata": {},
"source": [
"首先,我们生成两类线性不可分的二维圆形数据点作为我们的训练集和测试集。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "turkish-energy",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"先来看一下我们的训练集和测试集:\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 720x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# 生成训练集和测试集\n",
"X_train, y_train = make_circles(10, noise=0.05, factor=0.2)\n",
"X_test, y_test = make_circles(10, noise=0.05, factor=0.2)\n",
"\n",
"# 将生成的数据集进行可视化\n",
"fig, ax = plt.subplots(1, 2, figsize=[10, 4])\n",
"ax[0].scatter(X_train[:,0], X_train[:,1], \n",
" marker='o', c = matplotlib.cm.coolwarm(np.array(y_train, dtype=np.float32)))\n",
"ax[0].set_title('Train')\n",
"ax[1].set_title('Test')\n",
"ax[1].scatter(X_test[:,0], X_test[:,1], marker='v', c = matplotlib.cm.coolwarm(np.array(y_test, dtype=np.float32)))\n",
"\n",
"print(\"先来看一下我们的训练集和测试集:\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "federal-representation",
"metadata": {},
"outputs": [],
"source": [
"# 初始化进度条\n",
"bar_format_string = '{l_bar}{bar}|[{elapsed}<{remaining}, ' '{rate_fmt}{postfix}]'\n",
"pbar = tqdm(total=100, bar_format=bar_format_string)\n",
"pbar.close()\n",
"clear_output()"
]
},
{
"cell_type": "markdown",
"id": "educated-permission",
"metadata": {},
"source": [
"下面,我们来用 PaddleQuantum 来搭建量子核函数的计算电路:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "every-competition",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"检查是否满足 K(x, x) = 1? True\n"
]
}
],
"source": [
"# 初始化一个用来更新进度条的全局变量\n",
"N = 1\n",
"\n",
"# 通过 paddle quantum 模拟的 QKE 电路\n",
"def q_kernel_estimator(x1, x2):\n",
" \n",
" # 将数据类型转换为 tensor\n",
" x1 = paddle.to_tensor(x1)\n",
" x2 = paddle.to_tensor(x2)\n",
" \n",
" # 创建电路\n",
" cir = UAnsatz(2)\n",
" \n",
" # 添加对应第一个数据的编码电路\n",
" cir.iqp_encoding(x1, pattern=[[0, 1]])\n",
" \n",
" # 添加对应第二个数据的编码电路的逆电路\n",
" cir.iqp_encoding(x2, pattern=[[0, 1]], invert=True)\n",
" \n",
" # 用态矢量模式运行电路\n",
" fin_state = cir.run_state_vector()\n",
" \n",
" # 更新进度条\n",
" global pbar\n",
" global N\n",
" pbar.update(100/N)\n",
" \n",
" # 返回测量结果为 0...0 的概率\n",
" return (fin_state[0].conj() * fin_state[0]).real().numpy()[0]\n",
"\n",
"# 按照规范定义需要传入的 Kernel 矩阵函数\n",
"# 按照规范,输入应为两个数据列表\n",
"def q_kernel_matrix(X1, X2):\n",
" return np.array([[q_kernel_estimator(x1, x2) for x2 in X2] for x1 in X1])\n",
"\n",
"# 可视化决策函数(预测值),以及决策边界\n",
"def visualize_decision_bound(clf):\n",
" \n",
" # 创建一个 10x10 的网格\n",
" x_min, x_max = X_train[:,0].min(), X_train[:,0].max()\n",
" y_min, y_max = X_train[:,1].min(), X_train[:,1].max()\n",
" XX, YY = np.meshgrid(np.linspace(-1.2, 1.2, 10), \n",
" np.linspace(-1.2, 1.2, 10))\n",
" \n",
" # 计算分类器该网格上的预测值\n",
" Z = clf.decision_function(np.c_[XX.ravel(), YY.ravel()])\n",
" Z_qke = Z.reshape(XX.shape)\n",
" \n",
" # 可视化决策函数,以及决策边界\n",
" clear_output()\n",
" plt.contourf(XX, YY, Z_qke ,vmin=-1., vmax=1., levels=20,\n",
" cmap=matplotlib.cm.coolwarm, alpha=1)\n",
" plt.scatter(X_train[:,0], X_train[:,1], \n",
" c = matplotlib.cm.coolwarm(np.array(y_train, dtype=np.float32)),\n",
" edgecolor='black')\n",
" plt.scatter(X_test[:,0], X_test[:,1], marker='v', \n",
" c = matplotlib.cm.coolwarm(np.array(y_test, dtype=np.float32)),\n",
" edgecolor='black')\n",
" plt.contour(XX, YY, Z_qke, colors=['k', 'k', 'k'], linestyles=['--', '-', '--'],\n",
" levels=[-.2, 0, .2])\n",
"\n",
"# 作为检查量子核函数是否运行正常,我们可以检查 K(x, x) 是否等于 1\n",
"# 提示:根据内积的定义 <x, x> = 1\n",
"print('检查是否满足 K(x, x) = 1?',\n",
" bool(abs(q_kernel_estimator(np.array([1. ,1.]), np.array([1., 1.])) - 1) < 1e-8))"
]
},
{
"cell_type": "markdown",
"id": "requested-cameroon",
"metadata": {},
"source": [
"接下来,让我们尝试用量子核支持向量机(QKE-SVM)来进行数据分类:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "caring-daily",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"让我们看一下量子核支持向量机的分类效果如何:\n"
]
},
{
"data": {
"image/png": "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4h87aGpq2V5X18RvFm+IJygRERGRFAquEKtvCA5FplsmIiIi0l0UXCE2ZHAFVYPKW7WXlRlTPzAkhohEREREUiu4QszMuOFzk+nZI0FFebB7PSpLGH5ADz51/uiYoxMRERHZpyDPmpw8qS/3//AYfv/oRjZs3MV7pvTnpH8ZTFlZwdWdIiIikseyUpmY2TQzW25mK8xsTorls8ys1syWhrdLI8tmmtnr4W1mNuIBGNCvnI9/dBTXXD6JU08coiJMREREup2MR8TMLAHcDpwKrAWWmNnCFF98e7+7X5m07kDgK0A14MBz4bpbM41LREREpLvLxqHJY4AV7r4SwMzuA6YDyYVYKqcDD7v7W+G6DwPTgHuzEJeISN7787ObWfbaO63aE6XGBdNH0rtXQc4wESka2fgLHgGsiTxeCxybot+5ZnYC8Hfgs+6+Js26I1L9EjObDcwGGD1ak+5FpDgseWErv/zdetxbticSxrkfSpkuRSSP5Gri1G+Ase7+HuBh4J793YC7z3P3anevrqqqynqAIiLd0UXnj2k1x7WszJg+bRj9+5XFFJWIZEs2CrF1wKjI45Fh217uvsXd68KH84GjO7quiEhX644nHDUbNKCcD009gLLSfReqNjNmXjAm279KRGKQjUJsCTDRzMaZWTkwA1gY7WBmwyIPzwJeDe8vBk4zswFmNgA4LWwTEcmJyAlHZwBTgAvNbEqKrve7+xHhbX64bvMJR8cSzJf9SpjLsmrWjDFYSVCIlZUZHz71AAYNaH3hahHJPxkXYu7eAFxJUEC9Cjzg7q+Y2Y1mdlbY7Soze8XM/gZcBcwK130LuImgmFsC3Ng8cV9EJEf2nnDk7nuA5hOOOmLvCUfh2d7NJxxlVfOoWGnCNBomUmCycrqNuy8CFiW1XR+5fx1wXZp1FwALshGHiEgndPkJR9k42WjWjDEsXLxBo2EiBUZXORURaV9GJxxl42SjQQPK+eb1h3LpJ8d2an0R6Z5UiIlIscubE46OOWogfXvrTEmRQqJCTESKnU44EpHY6JLMIlLU3L3BzJpPOEoAC5pPOAJq3H0hwQlHZwENwFtETjgys+YTjkAnHInIflIhJiJFTycciUhcdGhSREREJCYqxERERERiokJMREREJCYqxERERERiokJMREREJCYqxERERERiokJMREREJCYqxERERERiokJM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\n",
"text/plain": [
"<Figure size 720x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# 创建进度条,并设置所需要的量子核函数计算数量 N\n",
"pbar = tqdm(total=100, \n",
" desc='训练 QKE-SVM 并分类中', \n",
" bar_format=bar_format_string)\n",
"N = len(X_train) ** 2 + len(X_train) ** 2 + len(X_train) * len(X_test)\n",
"\n",
"# 创建一个具有量子核函数的支持向量机\n",
"svm_qke = svm.SVC(kernel=q_kernel_matrix)\n",
"\n",
"# 根据训练数据计算支持向量机的决策平面\n",
"svm_qke.fit(X_train, y_train)\n",
"\n",
"# 计算支持向量机分别对于训练数据和测试数据的分类预测值\n",
"predict_svm_qke_train = svm_qke.predict(X_train)\n",
"predict_svm_qke_test = svm_qke.predict(X_test)\n",
"\n",
"# 计算准确率\n",
"accuracy_train = np.array(predict_svm_qke_train == y_train, dtype=int).sum()/len(y_train)\n",
"accuracy_test = np.array(predict_svm_qke_test == y_test, dtype=int).sum()/len(y_test)\n",
"\n",
"# 可视化分类预测结果\n",
"pbar.close()\n",
"clear_output()\n",
"fig, ax = plt.subplots(1, 2, figsize=[10, 4])\n",
"ax[0].scatter(X_train[:,0], X_train[:,1], marker='o', \n",
" c = matplotlib.cm.coolwarm(np.array(predict_svm_qke_train, dtype=np.float32)))\n",
"ax[0].set_title('Prediction on training set, accuracy={:.2f}'.format(accuracy_train))\n",
"ax[1].scatter(X_test[:,0], X_test[:,1], marker='v', \n",
" c = matplotlib.cm.coolwarm(np.array(predict_svm_qke_test, dtype=np.float32)))\n",
"ax[1].set_title('Prediction on testing set, accuracy={:.2f}'.format(accuracy_test))\n",
"print(\"让我们看一下量子核支持向量机的分类效果如何:\")"
]
},
{
"cell_type": "markdown",
"id": "distinguished-dependence",
"metadata": {},
"source": [
"更进一步的,我们还可以检查此时的决策函数平面以及决策边界:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "universal-genome",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"计算 QKE-SVM 的决策函数中: 100%|█████████████████████████████████████████████████████████████▉|[01:26<00:00, 1.16it/s]\n"
]
},
{
"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": [
"# 创建进度条,并设置所需要的量子核函数计算数量 N\n",
"pbar = tqdm(total=100, \n",
" desc='计算 QKE-SVM 的决策函数中', \n",
" bar_format=bar_format_string)\n",
"N = 10 ** 2 * len(X_train)\n",
" \n",
"# 可视化决策函数平面\n",
"visualize_decision_bound(svm_qke)\n",
"pbar.close()"
]
},
{
"cell_type": "markdown",
"id": "transsexual-swift",
"metadata": {},
"source": [
"可以看到,量子核函数可以很好的学习到数据中的非线性特征。实际上,量子核方法的表现取决于量子特征映射的设计。并且,对于如何设计更好的量子核函数的探究才刚刚开始:一方面,我们可以尝试不同的数据编码方式;另一方面,我们可以尝试通过训练量子特征映射的方式提升分类效果 [5-6];最后,我们还可以尝试一些不同的量子核函数形式 [7]。\n",
"\n",
"下面,作为拓展,我们也将展示一种特殊的量子核函数:投影量子核函数(projected quantum kernel)。"
]
},
{
"cell_type": "markdown",
"id": "scenic-circuit",
"metadata": {},
"source": [
"### 拓展:投影量子核函数\n",
"\n",
"上文中已经提到,量子核方法通过将经典信息映射到潜在的高维量子特征空间来分辨在经典空间不可分的信息。但是,当我们的量子特征空间-希尔伯特空间的维度太大的时候,所有映射到希尔伯特空间的量子态都会接近于相互垂直的状态,此时的核矩阵将会近似的变成一个单位矩阵 $K_{ij} = K(\\mathbf{x}_j, \\mathbf{x}_i) \\sim {I}$。为了避免这种维度问题的出现,我们需要首先从高维希尔伯特空间提取出足够的低维信息。投影量子核方法就是遵循了这个思路,即将量子态投影到新的经典空间,再在这个新的经典空间使用核方法。我们可以认为每一个投影是从不同的角度去观测希尔伯特空间的量子态,从足够多的角度测量这个量子态可以使我们获得足够重构这个态的经典信息。但在实际应用中,通常只需要从几个角度测量就能得到比较好的结果 [5]。 由于这个经典空间保留了部分希尔伯特空间中的重要特征,所以信息在这个经典空间的可分性优于原来的经典空间。\n",
"\n",
"投影量子核函数有很多不同的形式,这里我们举一个最为代表性的作为例子:\n",
"\n",
"$$\n",
"K^{PQ}(x_i,x_j) = \\exp\\left(-\\gamma\\sum\\limits_{k}\\sum\\limits_{P\\in \\mathcal{M}}( {\\rm Tr} (P\\rho(x_i)_k)-{\\rm Tr}(P\\rho(x_j)_k))^{2}\\right),\n",
"\\tag{13}\n",
"$$\n",
"\n",
"其中 $k$ 是用来标记多量子比特约化密度矩阵的下标,$\\mathcal{M}$ 是一个作用在多量子比特约化密度矩阵上的测量的集合。在这里,我们取 $k = 0, 1$,即两个单量子比特的约化密度矩阵,$M = \\{X, Y, Z \\}$,即一组 Pauli 测量。\n",
"\n",
"我们先尝试用 Paddle Quantum 来实现对应的投影量子核电路:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "artificial-hierarchy",
"metadata": {},
"outputs": [],
"source": [
"# 因为这次我们的特征映射的特征空间也是经典的,我们不妨先把该映射写出来\n",
"def projected_q_feature_map(x):\n",
" cir = UAnsatz(2)\n",
"\n",
" # 将经典数据转换为 Tensor\n",
" x = paddle.to_tensor(x)\n",
" \n",
" # 编码经典数据到对应的量子态上\n",
" cir.iqp_encoding(x, pattern=[[0, 1]])\n",
" \n",
" # 运行电路\n",
" cir.run_state_vector()\n",
" \n",
" # 更新进度条\n",
" global N\n",
" pbar.update(100/N)\n",
" \n",
" # 进行投影测量,返回其期望值作为经典特征向量\n",
" return [cir.expecval([[1.0, op_pauli]]).numpy()[0] \n",
" for op_pauli in ['z0', 'z1', 'x0', 'x1', 'y0', 'y1']]\n",
"\n",
"# 按照上文公式计算投影量子核函数\n",
"def p_quantum_kernel_estimator(x1, x2):\n",
" \n",
" # 分别得到特征向量,并计算核函数\n",
" p_feature_vector_1 = np.array(projected_q_feature_map(x1))\n",
" p_feature_vector_2 = np.array(projected_q_feature_map(x2))\n",
" \n",
" return np.exp(-((p_feature_vector_1 - p_feature_vector_2) ** 2).sum())\n",
"\n",
"# 类似地,按照规范定义传入支持向量机的核函数\n",
"def p_quantum_kernel_matrix(X1, X2):\n",
" return np.array([[p_quantum_kernel_estimator(x1, x2) for x2 in X2] for x1 in X1])"
]
},
{
"cell_type": "markdown",
"id": "baking-bridges",
"metadata": {},
"source": [
"接下来,让我们看一下如何用投影量子核支持向量机(PQK-SVM)来进行数据分类:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "chronic-terrorist",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"让我们看一下投影量子核支持向量机的分类效果如何:\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAmIAAAEICAYAAAD80ZhHAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Z1A+gAAAACXBIWXMAAAsTAAALEwEAmpwYAAAxCElEQVR4nO3deZwU9Z3/8ddnei7uc0DuQ0BBjddE45qoUVQ0iWg0ijkEV5fo6s9sNFkxhzEeCdkcmmxcI0GiySYeMYckIUu8cxiVUYkHSkQC4RIGBBSBYY7P74+qgZqe7plhuqdruvv9fDz6Md3f+lbNp7p7PvPpb32r2twdEREREcm9krgDEBERESlWKsREREREYqJCTERERCQmKsREREREYqJCTERERCQmKsREREREYqJCrA1mdreZ3Rze/4CZLe/kdn5gZl/ObnTdj5l9wczmZ7uviGRGuSw7lLekK+R9IWZmq8xsl5ntMLONYcLpne3f4+5/cveDOhDPLDP7c9K6l7n7TdmOKZvM7AkzuzSTbbj719y9Q9vYn765YGYnmdnauOPIJ2b2QTN73My2m9mqDvQ/xcxeM7Od4XpjIssqzGyBmb1tZm+a2dVdGnw3pFyWHdnIZeF2WuUE5a381x3zVt4XYqGPuHtv4CigGvhScgczK815VAVEz1/3YoG4/37fBRYAn2+vo5kNBn4JfBkYCNQA90e63ABMBMYAHwT+08ymZTnefKBcJgVLeSsNd8/rG7AKmBp5/E3gt+F9B64AXgf+EbZ9GFgKbAOeAt4TWfdI4HngnfDJvg+4OVx2ErA20ndU+ALVAluA7wOTgd1AI7AD2Bb2vbt5O+HjfwNWAG8BC4HhkWUOXBbGvA24HbA0+14B3AasD2+3ARXReIFrgE3ABuDiNNu5JYx5dxj399t4/r4LrAHeBp4DPhDZzg3A/4b3x4brzwT+CWwGvtjJvj2Ae4CtwKvAf0Zfi6R9MeDWcJ/fBl4CDo08X98Kf8dG4AfhtnsBu4CmcP93RF+TNt57c4A3wvfLMuCcpOX/FsbbvPyodO+d5Ock6XkpDR8/Eb5WfwnjnQBcHPkdK4FPJ8UwneD9/nYY6zTgY8BzSf2uBh7q5N/gVGBVO31mA09FHjc/5weHj9cDp0WW3wTcF3d+yeUN5bLb6LpcdjDwcBjncuD8yDpnEvx9vgOsAz5HmpyA8pbyVhfkrdiTT6Y3IskrfKO8AtwUPnaCP76B4Rv3yPCNfiyQCP+AVoVv9HJgNfBZoAw4D6gnRfIK1/1b+IfTC6gE3h8umwX8OSnGuyPbOZngD/ao8Pf+N/DHSF8Hfgv0B0aHb/ppafb9RuBpYAhQRZCMb4rE2xD2KSNINjuBAWm29QRwaVJbi+cvbPskMAgoJUiMbwKVyX+Q7Ptj/GH43B8O1AGTO9F3LvAkMAAYCbxI+oR2OkGB2J8guU0GhoXLbiX4ZzEQ6AP8Bvh68uu7H++9jxEk5xLgAoJPWsMiy9YB7w3jmEDwqamt987e5yTpeYkmtH8Ch4TPfxnwIeDA8HecGL7GzYnzGGA7cGoY4wiCf0gVBP+QJkd+1wvAueH9OQT/OFPeUjwPHUlo3wXuSGp7GTg3fF0dGBpZdh7wUtz5JZc3lMu6JJeF+7WG4J9/afjcbQamhMs3EH6gDN+LRyU/T5Ft3YDylvJWlvNW7Mkn0xtB8tkRPtmrgf9hX9HgwMmRvncQ/nFH2paHb4QTCKpbiyx7itTJ6ziCpFKaIp5ZtJ287gL+K7KsN0GSHBuJ+f2R5Q8Ac9Ls+xvAmUl/zKsi8e6KxkiQuN+XZltPkLoQOzlV/0ifrcDh4f0baJ2kRkb6PgvM6ETflcDpkWWXkj6hnQz8HXgfUBJpN4KEc2Ck7Tj2jS6clG6b+/FeXApMD+8vBj6Tok9b7529z0nS8xJNaDe2E8Ovm38vcCdwa5p+dwC3hPcPCV/Hik7ud0cS2l3A3KS2vxD8vYwK97MysuzU9rZZaDeUy7oklxEUG39K6nMn8JXw/j+BTwN9k/rsfZ4ibXv/RlHeavWcJD0vylsdvMV9rDZbznb3/u4+xt3/3d13RZatidwfA1xjZtuabwRP5vDwts7DZzO0Os3vGwWsdveGTsQ6PLpdd99BMMw7ItLnzcj9nQQJrt1thfeHRx5vSYqxrW2lE33+MLPPmdmr4UTHbUA/YHAb63d0X9rqOzwpjhYxRbn7YwSHVm4HNpnZPDPrS/ApuyfwXOS1/7+wvVPM7CIzWxrZ3qHsey5GEfxzSZbJewdavx5nmNnTZvZWGMOZHYgBgkMmHzczAz4FPODudZ2MqSN2AH2T2voSHJrYEXmcvKzYKJcFspnLxgDHJj1XnwAOCJefS/B3s9rMnjSz4zq43WbKW+1T3mpDoRRibYkmozUE1XT/yK2nu99LMDw9InyBm41Os801wOg0k2Y9RVvUeoLEAICZ9SI41LeuvR1pb1sE8a7vxHYgfdx7283sAwTzHM4nOCzQn2AI2VKvmjUbCIb2m41qq7O7f8/djwamAJMIJmVuJvhUfUjkte/nwcRoaP91ayE8c+aHwJXAoPC5eJl9z8UagqH3ZG29d94lSLrNDkjRJ/p6VAC/IJg/MjSMYVEHYsDdnwb2AB8APg78JLLdL4Rn7qW8pdpeB7xCcOim+Xf0CmN7xd23ErzGh0f6Hx6uI/sol3VMctxrgCeTnqve7n45gLsvcffpBIdFf00wcpdqO/tLeSuye5EYlLeSFEMhFvVD4DIzOzY8e6OXmX3IzPoAfyWYh3CVmZWZ2UcJjlWn8izBCzA33EalmR0fLtsIjDSz8jTr3gtcbGZHhG/IrwHPuPuqTuzPvcCXzKwqPLvjeuB/O7EdCOIe306fPgTPUS1QambX0/rTQld4ALjOzAaY2QiCJJKSmb03fH3LCBLEbqDJ3ZsIXv9bzWxI2HeEmZ0erroRGGRm/SLbOsnM0iW6XgTJpTbsezHBJ8tm84HPmdnR4XttQpgE23rvLAVOMLPRYRzXtfO8lBPMm6gFGszsDOC0yPK7CN5rp5hZSbi/B0eW/5jgU3i9u++9TIEHp+j3TneLPD8lZlZJMOfDwn1J977/FXComZ0brnM98KK7vxaJ5Uvha3wwwYThu9vZ/2KmXJZeci77LTDJzD4VPh9lYZ6YbGblZvYJM+vn7vUEk8ObIttpkRP2k/JWaspbSYqqEHP3GoIn6vsEx5ZXEBzrxd33AB8NH79FMK/gl2m20wh8hGAi4z8Jzui5IFz8GEFF/KaZbU6x7iMEp8L+guCNfSAwo5O7dDPB6bQvEpxl83zY1hnfBc4zs61m9r00fRYTDIv/neDQwW7aGG7PohsJnuN/AI8ADxJMik2lL0Hi2hrGuIXg7DOAawle86fN7O1wWwcBhH9Y9wIrLRiyH07wCfapVL/E3ZcB3yb4p7cROIxg7kDz8p8TnCn0M4Kh6l8DA9t677j7wwRnuL1IMHH3t209Ke7+DnAVQcLfSvAJcWFk+bMEE5RvJRi5fJKWow4/IUjCnf2HdwLBp/VFBCMYu4A/NC80s1fM7BNhLLUEh4BuCWM9lpbv+68QHI5YHcb5TXf/v07GVfCUy9rUIpeFfyenhbGtJziU+A2CYgCCQ1yrwpxwGcFhy3Q5YX8ob6WOQXkribWcRiDS/ZnZ5QQTYk/s4t8zH/i5uy/uyt8TFzPrQTDp+Sh3fz3ueEQKmfJWdhRi3tKFAaXbM7NhBIca/kpw8bxrCEYCupR3oytod5HLgSWFksxEuhPlrS5TcHlLhZjkg3KCU5rHEZzafx/Bqf3SSRZ8tYcBZ8cbiUjBUt7KskLNWzo0KSIiIhKTopqsLyIiItKd5OWhycGDB/vYsWPjDkNEcuS5557b7O6dvohld6L8JVJ82sphWSnEzGwBwRfQbnL3Q1MsN4JTipu/I2yWuz8fLpsJfCnserO739Pe7xs7diw1NTXZCF1E8oCZpbsyfN5R/hIpPm3lsGwdmryb4NvR0zmD4KyRiQTfZn5HGNhAgutwHEtwwcGvmNmALMUkIiIi0q1lpRBz9z8SXDgwnenAjz3wNNA/PLX3dOBhd38r/LqAh2m7oBMREREpGLmarD+ClldgXxu2pWtvxcxmm1mNmdXU1tZ2WaAiIiIiuZI3Z026+zx3r3b36qqqgpizKyIiIkUuV2dNrqPlN8+PDNvWAScltT+Ro5hEUqqra2T5Gzvo1TPB+DG9CM41ERGJX319Ey+99jbe1PoaoKNG9GTI4IoUa0l3lqtCbCFwpZndRzAxf7u7bzCzxcDXIhP0T6P9b24X6TL/99ibfPuOFZSUQGOjUzW4gm995TBGDOsRd2giIqxas5OrvvA3evVMEP2MuHt3E2dNG8bVl02MLzjplGxdvuJegpGtwWa2luBMyDIAd/8Bwbecn0nwDfI7Cb5ZHXd/y8xuApaEm7rR3dua9C/SZV5fuYNv/s/r1NU17W1bu34X//GlF7n/h8dQUqKRMRGJ18TxvTl4Yh9ee/2dFu3l5SWcf9bImKKSTGTrrMkL3X2Yu5e5+0h3v8vdfxAWYYRnS17h7ge6+2HuXhNZd4G7TwhvP8pGPCKd8cvfraO+vqlFmztsf6eel197O6aopKuZ2QIz22RmL6dZbmb2PTNbYWYvmtlRkWUzzez18DYzd1FLMbvi4vFUVuz7950ogfcfO4iRwzVyn4/yZrK+SFfbsnUPTU2t281g+9v1uQ9IcuVudB1EySNHHtafsaN77X2cKC1h9ifHxRiRZEKFmEjo+PcOavEps1l9fROHHtw3hogkF3QdRMlHzaNiGg3LfyrERELTTh7KsKGVVJTv+7OorCjhE+eOZkD/8hgjk5jpOojS7TSPirmj0bA8l5df+i3SFSoqEsz79lH8+vfreeIvtfTpXca5Hx7OcdWD4g5N8py7zwPmAVRXV7e+7oBIJ3zu3yfy7AtbNRqW51SIiUT0qExw4TmjuPCcUe13lmKh6yBKt3TwhD4cPKFP3GFIhnRoUkSkbQuBi8KzJ99HeB1EYDFwmpkNCCfpnxa2iYh0mEbERKSo6TqIIhInFWIiUtTc/cJ2ljtwRZplC4AFXRGXiBQHHZoUERERiYkKMREREZGYqBATERERiYkKMREREZGYqBATERERiYkKMREREZGYqBATERERiYkKMREREZGYqBATERERiUlWCjEzm2Zmy81shZnNSbH8VjNbGt7+bmbbIssaI8sWZiMeERERkXyQ8VccmVkCuB04FVgLLDGzhe6+rLmPu3820v//AUdGNrHL3Y/INA4RERGRfJONEbFjgBXuvtLd9wD3AdPb6H8hcG8Wfq+IiIhIXstGITYCWBN5vDZsa8XMxgDjgMcizZVmVmNmT5vZ2el+iZnNDvvV1NbWZiFsERERkXjlerL+DOBBd2+MtI1x92rg48BtZnZgqhXdfZ67V7t7dVVVVS5iFREREelS2SjE1gGjIo9Hhm2pzCDpsKS7rwt/rgSeoOX8MREREZGClY1CbAkw0czGmVk5QbHV6uxHMzsYGAD8NdI2wMwqwvuDgeOBZcnrioiIiBSijAsxd28ArgQWA68CD7j7K2Z2o5mdFek6A7jP3T3SNhmoMbO/AY8Dc6NnW4qI5IIuwSMiccn48hUA7r4IWJTUdn3S4xtSrPcUcFg2YhAR6QxdgkdE4qQr64tIsdMleEQkNirERKTYdfkleHT5HRFJR4WYiEjHdeoSPLr8joiko0JMRIqdLsEjIrFRISYixU6X4BGR2GTlrEkRkXzl7g1m1nwJngSwoPkSPECNuzcXZekuwXOnmTURfLDVJXhEZL+oEBORoqdL8IhIXHRoUkRERCQmKsREREREYlKwhyYbGp1nnnuLTZvrmDKpDwdN6BN3SCIiIiItFGQhtv7NXVwxZynv7myksbEJM+PIw/rz9S8eQmmpBgFFRESkeyjIquQr33yVLVv3sHNXI3V7nN11TTz/0jYeWJju0kAiIiIiuVdwhdhbW/ew4h87aGpq2V5X18RvFm+IJygRERGRFAquEKtvCA5FplsmIiIi0l0UXCE2ZHAFVYPKW7WXlRlTPzAkhohEREREUiu4QszMuOFzk+nZI0FFebB7PSpLGH5ADz51/uiYoxMRERHZpyDPmpw8qS/3//AYfv/oRjZs3MV7pvTnpH8ZTFlZwdWdIiIikseyUpmY2TQzW25mK8xsTorls8ys1syWhrdLI8tmmtnr4W1mNuIBGNCvnI9/dBTXXD6JU08coiJMREREup2MR8TMLAHcDpwKrAWWmNnCFF98e7+7X5m07kDgK0A14MBz4bpbM41LREREpLvLxqHJY4AV7r4SwMzuA6YDyYVYKqcDD7v7W+G6DwPTgHuzEJeISN7787ObWfbaO63aE6XGBdNH0rtXQc4wESka2fgLHgGsiTxeCxybot+5ZnYC8Hfgs+6+Js26I1L9EjObDcwGGD1ak+5FpDgseWErv/zdetxbticSxrkfSpkuRSSP5Gri1G+Ase7+HuBh4J793YC7z3P3anevrqqqynqAIiLd0UXnj2k1x7WszJg+bRj9+5XFFJWIZEs2CrF1wKjI45Fh217uvsXd68KH84GjO7quiEhX644nHDUbNKCcD009gLLSfReqNjNmXjAm279KRGKQjUJsCTDRzMaZWTkwA1gY7WBmwyIPzwJeDe8vBk4zswFmNgA4LWwTEcmJyAlHZwBTgAvNbEqKrve7+xHhbX64bvMJR8cSzJf9SpjLsmrWjDFYSVCIlZUZHz71AAYNaH3hahHJPxkXYu7eAFxJUEC9Cjzg7q+Y2Y1mdlbY7Soze8XM/gZcBcwK130LuImgmFsC3Ng8cV9EJEf2nnDk7nuA5hOOOmLvCUfh2d7NJxxlVfOoWGnCNBomUmCycrqNuy8CFiW1XR+5fx1wXZp1FwALshGHiEgndPkJR9k42WjWjDEsXLxBo2EiBUZXORURaV9GJxxl42SjQQPK+eb1h3LpJ8d2an0R6Z5UiIlIscubE46OOWogfXvrTEmRQqJCTESKnU44EpHY6JLMIlLU3L3BzJpPOEoAC5pPOAJq3H0hwQlHZwENwFtETjgys+YTjkAnHInIflIhJiJFTycciUhcdGhSREREJCYqxERERERiokJMREREJCYqxERERERiokJMREREJCYqxERERERiokJMREREJCYqxERERERiokJM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\n",
"text/plain": [
"<Figure size 720x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# 创建进度条,并设置所需要的量子核函数计算数量 N\n",
"pbar = tqdm(total=100, \n",
" desc='训练 PQK-SVM 并分类中', \n",
" bar_format=bar_format_string)\n",
"N = 2 * (len(X_train) ** 2 + len(X_train) ** 2 + len(X_train) * len(X_test))\n",
"\n",
"# 创建一个具有投影量子核函数的支持向量机\n",
"svm_pqk = svm.SVC(kernel=p_quantum_kernel_matrix)\n",
"\n",
"# 根据训练数据计算支持向量机的决策平面\n",
"svm_pqk.fit(X_train, y_train)\n",
"\n",
"# 计算支持向量机分别对于训练数据和测试数据的分类预测值\n",
"predict_svm_pqk_train = svm_pqk.predict(X_train)\n",
"predict_svm_pqk_test = svm_pqk.predict(X_test)\n",
"\n",
"# 计算准确率\n",
"accuracy_train = np.array(predict_svm_pqk_train == y_train, dtype=int).sum()/len(y_train)\n",
"accuracy_test = np.array(predict_svm_pqk_test == y_test, dtype=int).sum()/len(y_test)\n",
"\n",
"# 可视化分类结果\n",
"pbar.close()\n",
"clear_output()\n",
"fig, ax = plt.subplots(1, 2, figsize=[10, 4])\n",
"ax[0].scatter(X_train[:,0], X_train[:,1], marker='o', \n",
" c = matplotlib.cm.coolwarm(np.array(predict_svm_pqk_train, dtype=np.float32)))\n",
"ax[0].set_title('Prediction on training set, accuracy={:.2f}'.format(accuracy_train))\n",
"ax[1].scatter(X_test[:,0], X_test[:,1], marker='v', \n",
" c = matplotlib.cm.coolwarm(np.array(predict_svm_pqk_test, dtype=np.float32)))\n",
"ax[1].set_title('Prediction on testing set, accuracy={:.2f}'.format(accuracy_test))\n",
"print(\"让我们看一下投影量子核支持向量机的分类效果如何:\")"
]
},
{
"cell_type": "markdown",
"id": "irish-embassy",
"metadata": {},
"source": [
"同样的,我们检查一下此时的决策函数平面以及决策边界:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "chief-beach",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"计算 PQK-SVM 决策函数中: 100%|███████████████████████████████████████████████████████████████▉|[02:49<00:00, 1.69s/it]\n"
]
},
{
"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": [
"# 创建进度条,并设置所需要的量子核函数计算数量 N\n",
"pbar = tqdm(total=100, \n",
" desc='计算 PQK-SVM 决策函数中', \n",
" bar_format=bar_format_string)\n",
"N = 2 * 10 ** 2 * len(X_train)\n",
" \n",
"# 可视化决策函数平面\n",
"visualize_decision_bound(svm_pqk)\n",
"pbar.close()"
]
},
{
"cell_type": "markdown",
"id": "continuous-chance",
"metadata": {},
"source": [
"## 总结\n",
"\n",
"在量子机器学习的研究中,研究者们希望借助量子力学的特点设计出可以超越经典机器学习方法的模型。随着该领域的研究越发深入,人们发现量子机器学习和传统机器学习可以通过核方法建立起深入的联系。相比“传统”的量子神经网络,量子核方法把研究的重点放在了从经典数据空间到量子希尔伯特空间的特征映射,而不是变分量子电路。这为量子机器学习带来了新的研究思路,并为设计出实用的量子算法带来了新的可能性。因此,我们鼓励读者一起来思考如何设计出更好的量子核函数,并将其应用在更多样的数据集上。"
]
},
{
"cell_type": "markdown",
"id": "intimate-bible",
"metadata": {},
"source": [
"---\n",
"\n",
"## 参考资料\n",
"\n",
"[1] Schuld, Maria. \"Supervised quantum machine learning models are kernel methods.\" arXiv preprint [arXiv:2101.11020 (2021)](https://arxiv.org/abs/2101.11020).\n",
"\n",
"[2] Havlíček, Vojtěch, et al. \"Supervised learning with quantum-enhanced feature spaces.\" [Nature 567.7747 (2019): 209-212](https://arxiv.org/abs/1804.11326).\n",
"\n",
"[3] Liu, Yunchao, Srinivasan Arunachalam, and Kristan Temme. \"A rigorous and robust quantum speed-up in supervised machine learning.\" arXiv preprint [arXiv:2010.02174 (2020)](https://arxiv.org/abs/2010.02174).\n",
"\n",
"[4] Schuld, Maria, and Nathan Killoran. \"Quantum machine learning in feature Hilbert spaces.\" [Phys. Rev. Lett. 122.4 (2019): 040504](https://arxiv.org/abs/1803.07128).\n",
"\n",
"[5] Hubregtsen, Thomas, et al. \"Training Quantum Embedding Kernels on Near-Term Quantum Computers.\" arXiv preprint [arXiv:2105.02276(2021)](https://arxiv.org/abs/2105.02276).\n",
"\n",
"[6] Glick, Jennifer R., et al. \"Covariant quantum kernels for data with group structure.\" arXiv preprint [arXiv:2105.03406(2021)](https://arxiv.org/abs/2105.03406).\n",
"\n",
"[7] Huang, Hsin-Yuan, et al. \"Power of data in quantum machine learning.\" arXiv preprint [arXiv:2011.01938 (2020)](https://arxiv.org/abs/2011.01938).\n",
"\n",
"[8] Schölkopf, Bernhard, and Alexander J. Smola\"Learning with kernels: support vector machines, regularization, optimization, and beyond.\" [MIT Press(2002)](https://mitpress.mit.edu/books/learning-kernels)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"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_minor": 5
}
{
"cells": [
{
"cell_type": "markdown",
"id": "white-energy",
"metadata": {},
"source": [
"# Quantum Kernel Methods\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"id": "perfect-marker",
"metadata": {},
"source": [
"## Introduction\n",
"\n",
"One of the most important learning models for quantum machine learning applications in the noisy intermediate-scale quantum (NISQ) era is the parameterized quantum circuit. Although given its obvious analogy to classical neural networks, many refer to such quantum models as \"quantum neural networks\", it was shown that the mathematical form of such quantum machine learning models is actually much closer to kernel methods, a different kind of classical learning approach [1]. By combining classical kernel methods and the power of quantum models, quantum kernel methods can shed new light on how to approach a variety of machine learning problems, thus raising great interest in the field of quantum machine learning [2-7]. In this tutorial, we will introduce the basic ideas of quantum kernel methods and demonstrate how to classify data with two different quantum kernels.\n",
"\n",
"### Background\n",
"\n",
"In classical machine learning, kernel methods' basic idea is to map a low-dimensional data vector into a potentially high-dimensional feature space via a feature map, thus giving us the possibility to use linear methods to analyze non-linear features in the original data. As shown in Fig. 1, by mapping linearly inseparable 1D data into a 2D feature space, the feature vectors of the original data become linearly separable.\n",
"\n",
"![feature map](./figures/Qkernel-fig-featuremap.png \"Figure 1. feature map in kernel methods\")\n",
"<div style=\"text-align:center\">Figure 1. feature map in kernel methods </div>\n",
"\n",
"In practice, the feature space's dimensionality sometimes can be extremely large (even goes to infinity). So we do not wish to tackle these feature vectors directly. Another key idea in kernel methods is that we can implicitly analyze these feature vectors by only accessing their inner products in the feature space, which is noted as kernel functions $K(,)$:\n",
"\n",
"$$\n",
"K(\\mathbf{x}_i, \\mathbf{x}_j) = \\phi(\\mathbf{x}_j)^T \\phi(\\mathbf{x}_i),\n",
"\\tag{1}\n",
"$$\n",
"\n",
"with $\\phi()$ being the feature map. We note that in kernel methods, we do not need to express the feature map explicitly. Instead, we only need to compute the kernel function. This approach can introduce non-linearity into our models, giving us the ability to recognize intractable patterns in the original data space. \n",
"\n",
"The arguably most famous application of kernel methods is the support vector machine (SVM), which solves linear classification problems. Take a 2-classification problem as an example: Given data set $T = \\{ (\\mathbf{x}_1, y_1), ..., (\\mathbf{x}_m, y_m) \\} \\subset \\mathcal{X}\\times\\mathbb{Z}_2$, with a hyperplane $( \\mathbf{w}, b)$, a support vector machine can assign labels via the signs of the decision function, as:\n",
"\n",
"$$\n",
"y_{\\rm pred} = {\\rm sign}(\\langle \\mathbf{w}, \\mathbf{x} \\rangle + b).\n",
"\\tag{2}\n",
"$$\n",
"\n",
"But for linearly inseparable data, such linear classification schemes do not work. So again, as shown in Fig. 1, we can potentially find a better separation by mapping them into a feature space. For example, if we note the separating hyperplane in the feature space as $(\\mathbf{w}', b')$, then the decision function becomes:\n",
"\n",
"$$\n",
"y_{\\rm pred} = {\\rm sign}(\\langle \\mathbf{w}', \\phi(\\mathbf{x}) \\rangle + b').\n",
"\\tag{3}\n",
"$$\n",
"\n",
"Furthermore, by duality, we can write the hyperplane as $\\mathbf{w}' = \\sum_i \\alpha_i \\phi(\\mathbf{x_i})$ with Lagrangian multipliers $\\alpha_i$ [8]. Then, under the constraints $\\alpha_i \\geq 0$ and $\\sum_i y_i \\alpha_i=0$, we can compute the optimal $\\alpha_i^*$, thus the optimal hyperplane by maximizing \n",
"\n",
"$$\n",
"\\sum_i \\alpha_i - \\frac{1}{2} \\sum_{i, j} \\alpha_i \\alpha_j y_i y_j \\phi(\\mathbf{x}_j)^T \\phi(\\mathbf{x}_i).\n",
"\\tag{4}\n",
"$$\n",
"\n",
"Notice that in Eq. (4), we only need the inner products of feature vectors $\\phi(\\mathbf{x}_j)^T \\phi(\\mathbf{x}_i) = K(x_i, x_j)$, which is the above mentioned kernel function. As a result, we are able to find the optimal separating hyperplane in the feature space with SVM by only accessing the feature space through the kernel function. Furthermore, we can compute the predicted label as follows:\n",
"\n",
"$$\n",
"y_{\\rm pred} = {\\rm sign}(\\sum_i \\alpha^*_i \\langle \\phi(\\mathbf{x_i}), \\phi(\\mathbf{x}' \\rangle + b') = \n",
"{\\rm sign}(\\sum_i \\alpha^*_i K(\\mathbf{x}_i, \\mathbf{x}') + b').\n",
"\\tag{5}\n",
"$$\n",
"\n",
"Again, only kernel function is needed. \n",
"\n",
"Given the idea of classical kernel methods, we can easily understand the essential idea of quantum kernel methods. First, consider a quantum feature space, where we map a classical data vector $\\mathbf{x}$ into a quantum state $| \\phi(\\mathbf{x})\\rangle$ by a encoding circuit $U(\\mathbf{x})$ as follows:\n",
"\n",
"$$\n",
"U(\\mathbf{x}) | 0^{\\otimes N} \\rangle = | \\phi(\\mathbf{x}) \\rangle.\n",
"\\tag{6}\n",
"$$\n",
"\n",
"There are many discussions about how to best design an encoding circuit. We refer to our [data encoding tutorial](./DataEncoding_EN.ipynb) for a more detailed explanation. The encoding can also be regarded as a quantum feature map from classical data space to the Hilbert space. Based on this idea, we define a quantum kernel function as the inner products of two quantum feature vectors in the Hilbert space, which is\n",
"\n",
"$$\n",
"K^Q_{ij} = |\\langle \\phi(\\mathbf{x}_j) | \\phi(\\mathbf{x}_i) \\rangle |^2,\n",
"\\tag{7}\n",
"$$\n",
"\n",
"which can be further formulated as\n",
"\n",
"$$\n",
"|\\langle \\phi(\\mathbf{x}_j) | \\phi(\\mathbf{x}_i) \\rangle |^2 = |\\langle 0^{\\otimes N} | U^\\dagger(\\mathbf{x}_j) U(\\mathbf{x}_i) | 0^{\\otimes N} \\rangle |^2.\n",
"\\tag{8}\n",
"$$\n",
"\n",
"By running the quantum circuit as shown in Fig. 2, and measure the probability of observing $| 0^{\\otimes N} \\rangle $ at the output, we can estimate the quantum kernel function in Eq. (8). This way of constructing quantum kernels is also known as quantum kernel estimation (QKE). By replacing the classical kernel function in Eq. (4-5) with QKE, we can classify data in the quantum feature space with SVM. Given the potentially non-simulatable nature of such quantum kernels, there might exist a quantum advantage in recognizing classically intractable patterns. Such an advantage has been rigorously shown, with a constructed classically hard classification problem and a carefully designed quantum feature map [3].\n",
"\n",
"![QKE](./figures/Qkernel-fig-QKE.png \"Figure 2. Quantum kernel estimation circuit\")\n",
"<div style=\"text-align:center\">Figure 2. Quantum kernel estimation circuit </div>\n",
"\n",
"![illustration](./figures/Qkernel-fig-illustrationEN.png \"Figure 3. Classical kernel methods and quantum kernel methods\")\n",
"<div style=\"text-align:center\">Figure 3. Classical kernel methods and quantum kernel methods </div>"
]
},
{
"cell_type": "markdown",
"id": "parental-tampa",
"metadata": {},
"source": [
"### Connections between quantum machine learning and kernel methods\n",
"\n",
"In quantum machine learning models, a quantum encoding circuit is often used to encode classical data into a quantum state\n",
"\n",
"$$\n",
"| \\phi(x) \\rangle = U (x) | 0^{\\otimes N} \\rangle,\n",
"\\tag{9}\n",
"$$\n",
"\n",
"where $U(x)$ is a parameterized quantum circuit depending on the data vector $x$. Like we mentioned above, such quantum encoding circuit can be considered as a quantum feature map. Then, consider a \"quantum neural network\" is applied to the encoding state, in which the quantum circuit is composed of a set of parameterized gates with variational parameters. We have the final state as\n",
"\n",
"$$\n",
"| \\psi \\rangle = U_{\\rm QNN}(\\theta)U (\\mathbf{x}) | 0^{\\otimes N} \\rangle,\n",
"\\tag{10}\n",
"$$\n",
"\n",
"where $U_{\\rm QNN}(\\theta)$ is the quantum neural network with parameters $\\theta$. Finally we perform a measurement $\\mathcal{M}$ on the final state as the output of our model, its expectation value can be computed as\n",
"\n",
"$$\n",
"\\langle \\mathcal{M} \\rangle = \\langle \\psi | \\mathcal{M} | \\psi \\rangle = \\langle \\phi(\\mathbf{x}) | U^\\dagger_{\\rm QNN}(\\theta) \\mathcal{M} U_{\\rm QNN}(\\theta)| \\phi(\\mathbf{x}) \\rangle.\n",
"\\tag{11}\n",
"$$\n",
"\n",
"Suppose we write the measurement in its operator form $| \\sigma \\rangle \\langle \\sigma |$, then Eq. (11) can be further reformulated as \n",
"\n",
"$$\n",
"\\langle \\phi(\\mathbf{x}) | \\sigma'(\\theta) \\rangle \\langle \\sigma' (\\theta) | \\phi(x) \\rangle = \n",
"|\\langle \\sigma' (\\theta) | \\phi(\\mathbf{x}) \\rangle|^2,\n",
"\\tag{12}\n",
"$$\n",
"\n",
"where $| \\sigma'(\\theta) \\rangle = U^\\dagger_{\\rm QNN}(\\theta) | \\sigma \\rangle$. From Eq. (12), QNN together with a measurement can also be seen as a parameterized measurement operator, which is used to compute the inner product with the data encoding state in the Hilbert space, which is, the kernel function. This is why we mentioned in the introduction that the mathematical form of parameterized quantum circuits is closely related to kernel methods."
]
},
{
"cell_type": "markdown",
"id": "adequate-association",
"metadata": {},
"source": [
"## Kernel-based Classification with Paddle Quantum\n",
"\n",
"> It is required to have [`sklearn`](https://scikit-learn.org/stable/install.html) packages installed for the support vector machine. Readers may run the following block to install the relevant packages:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "automatic-timeline",
"metadata": {},
"outputs": [],
"source": [
"from IPython.display import clear_output\n",
"\n",
"!pip install scikit-learn\n",
"clear_output()"
]
},
{
"cell_type": "markdown",
"id": "existing-devon",
"metadata": {},
"source": [
"In this tutorial, we will demonstrate how to classify data using a support vector machine with a kernel computed by Paddle Quantum."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "literary-feature",
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"import matplotlib\n",
"import numpy as np\n",
"import paddle\n",
"from numpy import pi as PI\n",
"from matplotlib import pyplot as plt\n",
"\n",
"from paddle import matmul, transpose\n",
"from paddle_quantum.circuit import UAnsatz\n",
"\n",
"import sklearn\n",
"from sklearn import svm\n",
"from sklearn.datasets import fetch_openml, make_moons, make_circles\n",
"from sklearn.model_selection import train_test_split\n",
"\n",
"from IPython.display import clear_output\n",
"from tqdm import tqdm"
]
},
{
"cell_type": "markdown",
"id": "imperial-license",
"metadata": {},
"source": [
"For the training and testing set, we generate some 2D circle data that has 2 classes."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "literary-district",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Let's first see our training and testing set:\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 720x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# Generate data set\n",
"X_train, y_train = make_circles(10, noise=0.05, factor=0.2)\n",
"X_test, y_test = make_circles(10, noise=0.05, factor=0.2)\n",
"\n",
"# Visualize respectively the training and testing set\n",
"fig, ax = plt.subplots(1, 2, figsize=[10, 4])\n",
"ax[0].scatter(X_train[:,0], X_train[:,1], \n",
" marker='o', c = matplotlib.cm.coolwarm(np.array(y_train, dtype=np.float32)))\n",
"ax[0].set_title('Train')\n",
"ax[1].set_title('Test')\n",
"ax[1].scatter(X_test[:,0], X_test[:,1], marker='v', c = matplotlib.cm.coolwarm(np.array(y_test, dtype=np.float32)))\n",
"\n",
"print(\"Let's first see our training and testing set:\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "explicit-wayne",
"metadata": {},
"outputs": [],
"source": [
"# Initialize the progress bar\n",
"bar_format_string = '{l_bar}{bar}|[{elapsed}<{remaining}, ' '{rate_fmt}{postfix}]'\n",
"pbar = tqdm(total=100, bar_format=bar_format_string)\n",
"pbar.close()\n",
"clear_output()"
]
},
{
"cell_type": "markdown",
"id": "asian-preliminary",
"metadata": {},
"source": [
"Now, let's see how to implement a quantum kernel with Paddle Quantum:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "ideal-jaguar",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Check if K(x, x) = 1? True\n"
]
}
],
"source": [
"# Global variable for manual updates of the progress bar\n",
"N = 1\n",
"\n",
"# The QKE circuit simulated by paddle quantm\n",
"def q_kernel_estimator(x1, x2):\n",
" \n",
" # Transform data vectors into tensors\n",
" x1 = paddle.to_tensor(x1)\n",
" x2 = paddle.to_tensor(x2)\n",
" \n",
" # Create the circuit\n",
" cir = UAnsatz(2)\n",
" \n",
" # Add the encoding circuit for the first data vector\n",
" cir.iqp_encoding(x1, pattern=[[0, 1]])\n",
" \n",
" # Add inverse of the encoding circuit for the second data vector\n",
" cir.iqp_encoding(x2, pattern=[[0, 1]], invert=True)\n",
" \n",
" # Run the circuit with state vector mode\n",
" fin_state = cir.run_state_vector()\n",
" \n",
" # Update the progress bar\n",
" global N\n",
" pbar.update(100/N)\n",
" \n",
" # Return the probability of measuring 0...0 \n",
" return (fin_state[0].conj() * fin_state[0]).real().numpy()[0]\n",
"\n",
"# Define a kernel matrix function, for which the input should be two list of vectors\n",
"# This is needed to customize the SVM kernel\n",
"def q_kernel_matrix(X1, X2):\n",
" return np.array([[q_kernel_estimator(x1, x2) for x2 in X2] for x1 in X1])\n",
"\n",
"# Visualize the decision function, boundary, and margins of +- 0.2\n",
"def visualize_decision_bound(clf):\n",
" \n",
" # Create a 10x10 mesh in the data plan \n",
" x_min, x_max = X_train[:,0].min(), X_train[:,0].max()\n",
" y_min, y_max = X_train[:,1].min(), X_train[:,1].max()\n",
" XX, YY = np.meshgrid(np.linspace(-1.2, 1.2, 10), \n",
" np.linspace(-1.2, 1.2, 10))\n",
" \n",
" # Calculate the decision function value on the 10x10 mesh\n",
" Z = clf.decision_function(np.c_[XX.ravel(), YY.ravel()])\n",
" Z_qke = Z.reshape(XX.shape)\n",
" \n",
" # visualize the decision function and boundary\n",
" clear_output()\n",
" plt.contourf(XX, YY, Z_qke ,vmin=-1., vmax=1., levels=20,\n",
" cmap=matplotlib.cm.coolwarm, alpha=1)\n",
" plt.scatter(X_train[:,0], X_train[:,1], \n",
" c = matplotlib.cm.coolwarm(np.array(y_train, dtype=np.float32)),\n",
" edgecolor='black')\n",
" plt.scatter(X_test[:,0], X_test[:,1], marker='v', \n",
" c = matplotlib.cm.coolwarm(np.array(y_test, dtype=np.float32)),\n",
" edgecolor='black')\n",
" plt.contour(XX, YY, Z_qke, colors=['k', 'k', 'k'], linestyles=['--', '-', '--'],\n",
" levels=[-.2, 0, .2])\n",
"\n",
"# To make sure we didn't make any mistake, check if the kernel function satisfies K(x, x)=1\n",
"print('Check if K(x, x) = 1?',\n",
" bool(abs(q_kernel_estimator(np.array([1. ,1.]), np.array([1., 1.])) - 1) < 1e-8))"
]
},
{
"cell_type": "markdown",
"id": "close-description",
"metadata": {},
"source": [
"Then, let's try to use a support vector machine with a quantum kernel (QKE-SVM) to classify our data:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "driving-belize",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Let's see how the QKE-SVM performs on the training on both the training and testing data:\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 720x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# Create the progress bar and the total kernel evaluation number N needed for training and prediction\n",
"pbar = tqdm(total=100, \n",
" desc='Training and predicting with QKE-SVM', \n",
" bar_format=bar_format_string)\n",
"N = len(X_train) ** 2 + len(X_train) ** 2 + len(X_train) * len(X_test)\n",
"\n",
"# Create a support vector machine with a quantum kernel\n",
"svm_qke = svm.SVC(kernel=q_kernel_matrix)\n",
"\n",
"# Train the svm with training data\n",
"svm_qke.fit(X_train, y_train)\n",
"\n",
"# See how the svm classifies the training and testing data\n",
"predict_svm_qke_train = svm_qke.predict(X_train)\n",
"predict_svm_qke_test = svm_qke.predict(X_test)\n",
"\n",
"# Calculate the accuracy\n",
"accuracy_train = np.array(predict_svm_qke_train == y_train, dtype=int).sum()/len(y_train)\n",
"accuracy_test = np.array(predict_svm_qke_test == y_test, dtype=int).sum()/len(y_test)\n",
"\n",
"# Visualize the result\n",
"pbar.close()\n",
"clear_output()\n",
"fig, ax = plt.subplots(1, 2, figsize=[10, 4])\n",
"ax[0].scatter(X_train[:,0], X_train[:,1], marker='o', \n",
" c = matplotlib.cm.coolwarm(np.array(predict_svm_qke_train, dtype=np.float32)))\n",
"ax[0].set_title('Prediction on training set, accuracy={:.2f}'.format(accuracy_train))\n",
"ax[1].scatter(X_test[:,0], X_test[:,1], marker='v', \n",
" c = matplotlib.cm.coolwarm(np.array(predict_svm_qke_test, dtype=np.float32)))\n",
"ax[1].set_title('Prediction on testing set, accuracy={:.2f}'.format(accuracy_test))\n",
"print(\"Let's see how the QKE-SVM performs on the training on both the training and testing data:\")"
]
},
{
"cell_type": "markdown",
"id": "radio-freeze",
"metadata": {},
"source": [
"We can also visualize the decision function, also the decision boundary with margins of $\\pm 0.2$:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "dynamic-colonial",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Calculating the decision function of QKE-SVM: 100%|██████████████████████████████████████████▉|[01:24<00:00, 1.18it/s]\n"
]
},
{
"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": [
"# Create the progress bar and the total kernel evaluation number N needed for visualizing the decision function\n",
"pbar = tqdm(total=100, \n",
" desc='Calculating the decision function of QKE-SVM', \n",
" bar_format=bar_format_string)\n",
"N = 10 ** 2 * len(X_train)\n",
" \n",
"# Visualize the decision function\n",
"visualize_decision_bound(svm_qke)\n",
"pbar.close()"
]
},
{
"cell_type": "markdown",
"id": "quantitative-reliance",
"metadata": {},
"source": [
"We can see that the quantum kernel has the ability to learn non-linearity correctly. As a matter of fact, the performance of quantum kernel methods in classification depends on whether the quantum feature map can distinguish non-trivial patterns hidden in the data. Currently, people are still exploring how to design a good quantum kernel: First, we may try different designs of encoding circuits; Second, we can train the quantum feature map to improve its classification accuracy [5-6]; Finally, we can also try variants of the quantum kernels [7]. \n",
"\n",
"In the following part, we will introduce another special kind of quantum kernel - projected quantum kernel. "
]
},
{
"cell_type": "markdown",
"id": "residential-williams",
"metadata": {},
"source": [
"### Projected quantum kernel\n",
"\n",
"It was mentioned above that quantum kernel methods can potentially distinguish intractable patterns by mapping classical data vectors into a quantum feature space via a quantum feature map. However, as the quantum feature space - the Hilbert space's dimensionality grows exponentially with the number of qubits, nearly all quantum states will be perpendicular to each other when we have a large number of qubits. Then the kernel matrix will just become an identity matrix $K_{ij} = K(\\mathbf{x}_j, \\mathbf{x}_i) \\sim {I}$, and the kernel methods would fail. To avoid this problem caused by extra dimensionality, we first need to extract features from the Hilbert space and then construct the kernel function with these extracted features. Following this idea, a variant of quantum kernel - projected quantum kernel is proposed : By projecting the quantum feature vectors back into the classical space with a set of measurements, the dimensionality problem is mitigated [7]. Also, as the projection can preserve important features of the quantum feature space, the projected kernel can still gain a quantum advantage. \n",
"\n",
"There are several kinds of projected quantum kernels, here we choose the most rudimentary one:\n",
"\n",
"$$\n",
"K^{P}(x_i,x_j) = \\exp\\left(-\\gamma\\sum\\limits_{k}\\sum\\limits_{P\\in \\mathcal{M}}( {\\rm Tr} (P\\rho(x_i)_k)-{\\rm Tr}(P\\rho(x_j)_k))^{2}\\right),\n",
"\\tag{13}\n",
"$$\n",
"\n",
"where $\\rho(x_i)_k$ is the reduce density matrix of qubits $k$, $\\mathcal{M}$ a set of measurements on the reduce density matrix. Here we take $k = 0, 1$ and $M = \\{X, Y, Z \\}$, which means using Pauli measurements to measure every single qubit at the output.\n",
"\n",
"Let's first try to implement a projected quantum kernel circuit with Paddle Quantum:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "acute-environment",
"metadata": {},
"outputs": [],
"source": [
"# First we can create a circuit to calculate the feature map \n",
"def projected_q_feature_map(x):\n",
" cir = UAnsatz(2)\n",
"\n",
" # turn data into tensor\n",
" x = paddle.to_tensor(x)\n",
" \n",
" # encode the classical data into a quantum state\n",
" cir.iqp_encoding(x, pattern=[[0, 1]])\n",
" \n",
" # run the circuit with state vector mode\n",
" cir.run_state_vector()\n",
" \n",
" # Update the progress bar\n",
" global N\n",
" pbar.update(100/N)\n",
" \n",
" # to measure the final state with Pauli measurement on every single qubit\n",
" return [cir.expecval([[1.0, op_pauli]]).numpy()[0] \n",
" for op_pauli in ['z0', 'z1', 'x0', 'x1', 'y0', 'y1']]\n",
"\n",
"# to compute the projected quantum kernel based on the feature vectors\n",
"def p_quantum_kernel_estimator(x1, x2):\n",
" \n",
" # compute the feature vector of each data and return the kernel function value\n",
" p_feature_vector_1 = np.array(projected_q_feature_map(x1))\n",
" p_feature_vector_2 = np.array(projected_q_feature_map(x2))\n",
" \n",
" return np.exp(-((p_feature_vector_1 - p_feature_vector_2) ** 2).sum())\n",
"\n",
"# similarly, define the kernel matrix as required \n",
"def p_quantum_kernel_matrix(X1, X2):\n",
" return np.array([[p_quantum_kernel_estimator(x1, x2) for x2 in X2] for x1 in X1])"
]
},
{
"cell_type": "markdown",
"id": "round-bandwidth",
"metadata": {},
"source": [
"Then, we replace the quantum kernel in the support vector machine with a projected quantum kernel, and see how the projected kernel performs on this classification task:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "alert-royal",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Let's see how the PQK-SVM performs on the training on both the training and testing data:\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 720x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# Set the progress bar and the total kernel evaluation number N needed for training and prediction\n",
"pbar = tqdm(total=100, \n",
" desc='Training and predicting with PQK-SVM', \n",
" bar_format=bar_format_string)\n",
"N = 2 * (len(X_train) ** 2 + len(X_train) ** 2 + len(X_train) * len(X_test))\n",
"\n",
"# Create a support vector machine with a quantum kernel\n",
"svm_pqk = svm.SVC(kernel=p_quantum_kernel_matrix)\n",
"\n",
"# Train the svm with training data\n",
"svm_pqk.fit(X_train, y_train)\n",
"\n",
"# See how the svm classifies the training and testing data\n",
"predict_svm_pqk_train = svm_pqk.predict(X_train)\n",
"predict_svm_pqk_test = svm_pqk.predict(X_test)\n",
"\n",
"# Calculate the accuracy\n",
"accuracy_train = np.array(predict_svm_pqk_train == y_train, dtype=int).sum()/len(y_train)\n",
"accuracy_test = np.array(predict_svm_pqk_test == y_test, dtype=int).sum()/len(y_test)\n",
"\n",
"# Visualize the result\n",
"pbar.close()\n",
"clear_output()\n",
"fig, ax = plt.subplots(1, 2, figsize=[10, 4])\n",
"ax[0].scatter(X_train[:,0], X_train[:,1], marker='o', \n",
" c = matplotlib.cm.coolwarm(np.array(predict_svm_pqk_train, dtype=np.float32)))\n",
"ax[0].set_title('Prediction on training set, accuracy={:.2f}'.format(accuracy_train))\n",
"ax[1].scatter(X_test[:,0], X_test[:,1], marker='v', \n",
" c = matplotlib.cm.coolwarm(np.array(predict_svm_pqk_test, dtype=np.float32)))\n",
"ax[1].set_title('Prediction on testing set, accuracy={:.2f}'.format(accuracy_test))\n",
"print(\"Let's see how the PQK-SVM performs on the training on both the training and testing data:\")"
]
},
{
"cell_type": "markdown",
"id": "unavailable-stretch",
"metadata": {},
"source": [
"Let's also check the decision function given by the PQK-SVM:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "connected-final",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Calculating the decision function for PQK-SVM: 100%|█████████████████████████████████████████▉|[02:37<00:00, 1.58s/it]\n"
]
},
{
"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": [
"# Set the progress bar and the total kernel evaluation number N needed for visualizing the decision function\n",
"pbar = tqdm(total=100, \n",
" desc='Calculating the decision function for PQK-SVM', \n",
" bar_format=bar_format_string)\n",
"N = 2 * 10 ** 2 * len(X_train)\n",
" \n",
"# Clear the progress bar and visualize the decision function\n",
"visualize_decision_bound(svm_pqk)\n",
"pbar.close()"
]
},
{
"cell_type": "markdown",
"id": "italic-failing",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"In quantum machine learning, people hope the design learning models which can gain quantum advantage by exploring the nature of quantum mechanics' laws. Recently, many connections are made between these quantum models and kernel methods, one of the most important classical machine learning approaches. In comparison to considering a parameterized quantum circuit as a \"quantum neural network\", where we focus on the variational ansatz $U(\\theta)$, the quantum kernel methods emphasize the importance of quantum feature map $U(x)$, which describes how the classical data vectors is mapped to the quantum states. This brings new perspectives to how we can design novel quantum machine learning algorithms. Therefore, we encourage readers to together explore the performance of various quantum kernel designs on different data sets.\n"
]
},
{
"cell_type": "markdown",
"id": "external-sterling",
"metadata": {},
"source": [
"---\n",
"\n",
"## References\n",
"\n",
"[1] Schuld, Maria. \"Supervised quantum machine learning models are kernel methods.\" arXiv preprint [arXiv:2101.11020 (2021)](https://arxiv.org/abs/2101.11020).\n",
"\n",
"[2] Havlíček, Vojtěch, et al. \"Supervised learning with quantum-enhanced feature spaces.\" [Nature 567.7747 (2019): 209-212](https://arxiv.org/abs/1804.11326).\n",
"\n",
"[3] Liu, Yunchao, Srinivasan Arunachalam, and Kristan Temme. \"A rigorous and robust quantum speed-up in supervised machine learning.\" arXiv preprint [arXiv:2010.02174 (2020)](https://arxiv.org/abs/2010.02174).\n",
"\n",
"[4] Schuld, Maria, and Nathan Killoran. \"Quantum machine learning in feature Hilbert spaces.\" [Phys. Rev. Lett. 122.4 (2019): 040504](https://arxiv.org/abs/1803.07128).\n",
"\n",
"[5] Hubregtsen, Thomas, et al. \"Training Quantum Embedding Kernels on Near-Term Quantum Computers.\" arXiv preprint [arXiv:2105.02276(2021)](https://arxiv.org/abs/2105.02276).\n",
"\n",
"[6] Glick, Jennifer R., et al. \"Covariant quantum kernels for data with group structure.\" arXiv preprint [arXiv:2105.03406(2021)](https://arxiv.org/abs/2105.03406).\n",
"\n",
"[7] Huang, Hsin-Yuan, et al. \"Power of data in quantum machine learning.\" arXiv preprint [arXiv:2011.01938 (2020)](https://arxiv.org/abs/2011.01938).\n",
"\n",
"[8] Schölkopf, Bernhard, and Alexander J. Smola\"Learning with kernels: support vector machines, regularization, optimization, and beyond.\" [MIT Press(2002)](https://mitpress.mit.edu/books/learning-kernels)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"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_minor": 5
}
......@@ -304,7 +304,6 @@
"M = random_M_generator()\n",
"M_err = np.copy(M)\n",
"\n",
"\n",
"# 打印结果\n",
"print('我们想要分解的矩阵 M 是:')\n",
"print(M)\n",
......@@ -351,9 +350,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### 量子神经网络的构造\n",
"\n",
"我们搭建如下的结构:"
"我们搭建如下的量子神经网络结构:"
]
},
{
......@@ -920,7 +917,7 @@
"source": [
"_______\n",
"\n",
"## 参考文献\n",
"## 参考文献\n",
"\n",
"[1] Wang, X., Song, Z. & Wang, Y. Variational Quantum Singular Value Decomposition. [arXiv:2006.02336 (2020).](https://arxiv.org/abs/2006.02336)"
]
......
......@@ -262,9 +262,7 @@
"source": [
"### Case 1: Decompose a randomly generated $8\\times8$ complex matrix\n",
"\n",
"Then we look at a specific example, which can better explain the overall process.\n",
"\n",
"#### Define matrix $M$"
"Then we look at a specific example, which can better explain the overall process."
]
},
{
......@@ -322,13 +320,6 @@
"print(D)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Hyper-parameters"
]
},
{
"cell_type": "code",
"execution_count": 6,
......@@ -366,8 +357,6 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Building a quantum neural network\n",
"\n",
"We design QNN with the following structure:"
]
},
......@@ -414,7 +403,6 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Training model and loss function\n",
"Then we complete the main part of the algorithm:"
]
},
......@@ -543,9 +531,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Error analysis\n",
"\n",
"We will explore the accuracy of the quantum version of singular value decomposition. In the above section, we mentioned that the original matrix can be expressed with less information obtained by decomposition. Specifically, it uses the first $T$ singular values ​​and the first $T$ left and right singular vectors to reconstruct a matrix:\n",
"We now explore the accuracy of the quantum version of singular value decomposition. In the above section, we mentioned that the original matrix can be expressed with less information obtained by decomposition. Specifically, it uses the first $T$ singular values and the first $T$ left and right singular vectors to reconstruct a matrix:\n",
"\n",
"$$\n",
"M_{re}^{(T)} = UDV^{\\dagger}, \\tag{4}\n",
......@@ -613,8 +599,7 @@
"plt.xlabel('Singular Value Used (Rank)', fontsize = 14)\n",
"plt.ylabel('Norm Distance', fontsize = 14)\n",
"leg = plt.legend(frameon=True)\n",
"leg.get_frame().set_edgecolor('k')\n",
"# plt.savefig(\"vqsvd-fig-error.png\", bbox_inches='tight', dpi=600)"
"leg.get_frame().set_edgecolor('k')"
]
},
{
......@@ -934,11 +919,9 @@
"source": [
"_______\n",
"\n",
"## References\n",
"\n",
"## References:\n",
"\n",
"[1] Wang, X., Song, Z. & Wang, Y. Variational Quantum Singular Value Decomposition. [arXiv:2006.02336 (2020).](https://arxiv.org/abs/2006.02336)\n",
"\n"
"[1] Wang, X., Song, Z. & Wang, Y. Variational Quantum Singular Value Decomposition. [arXiv:2006.02336 (2020).](https://arxiv.org/abs/2006.02336)"
]
}
],
......
{
"cells": [
{
"cell_type": "markdown",
"id": "chronic-tunisia",
"metadata": {},
"source": [
"# 变分影子量子学习\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"id": "metric-peace",
"metadata": {},
"source": [
"## 概览\n",
"\n",
"本教程我们将讨论变分影子量子学习(variational shadow quantum learning, VSQL)[1] 的原理,以及如何使用 VSQL 来完成一个**二分类**任务。VSQL 是一个在监督学习框架下的量子–经典混合算法。它使用了参数化量子电路(parameterized quantum circuit, PQC)和经典影子(classical shadow),和通常使用的变分量子算法(variational quantum alogorithm, VQA)不同的是,VSQL 只从子空间获取局部特征,而不是从整个希尔伯特空间获取特征。\n",
"\n",
"### 背景\n",
"\n",
"我们考虑一个 $k$ 分类问题。输入是一个由 $N$ 个带标签的数据点组成的集合 $D=\\left\\{(\\mathbf{x}^i, \\mathbf{y}^i)\\right\\}_{i=1}^{N}$,这里的 $\\mathbf{x}^i\\in\\mathbb{R}^{m}$ 表示数据点,$\\mathbf{y}^i$ 是这个数据点的标签。**学习过程的目的在于训练一个能尽可能准确预测所有数据点标签的模型 $\\mathcal{F}$。** 我们需要注意,$\\mathbf{y}^i$ 是一个长度为 $k$ 的独热向量(one-hot vector),将标签值表示为独热向量是机器学习领域中的常规做法。我们举一个例子,当 $k=3$ 时,$\\mathbf{y}^{a}=[1, 0, 0]^\\text{T}$、$\\mathbf{y}^{b}=[0, 1, 0]^\\text{T}$ 和 $\\mathbf{y}^{c}=[0, 0, 1]^\\text{T}$ 分别表示第 $a$ 个、第 $b$ 个和第 $c$ 个数据点属于第一类、第二类和第三类。 \n",
"在 VSQL 中,$\\mathcal{F}$ 由两部分组成:参数化局部量子电路和经典全连接神经网络(fully-connected neural network, FCNN)。首先,我们需要预处理经典信息,将经典信息编码到量子态。然后我们以卷积的方式将 $U(\\mathbf{\\theta})$ 连续作用在局部量子比特上,这里的 $\\mathbf{\\theta}$ 是参数化局部电路的参数。在这些局部量子比特上进行测量就能得到我们想要的期望值。除此之外,我们还需要一个经典 FCNN 来做数据的后处理。 \n",
"我们可以把 VSQL 得到的 $\\mathcal{F}$ 的输出写为 $\\tilde{\\mathbf{y}}^i = \\mathcal{F}(\\mathbf{x}^i)$。这里的 $\\tilde{\\mathbf{y}}^i$ 是一个概率分布,$\\tilde{y}^i_j$ 表示第 $i$ 个数据点属于第 $j$ 类的概率。为了尽可能地预测到准确的标签,我们将预测标签 $\\tilde{\\mathbf{y}}^i$ 和实际标签 $\\mathbf{y}^i$ 之间的累计差距作为损失函数 $\\mathcal{L}$ 进行优化: \n",
"\n",
"$$\n",
"\\mathcal{L}(\\mathbf{\\theta}, \\mathbf{W}, \\mathbf{b}) = -\\frac{1}{N}\\sum\\limits_{i=1}^{N}\\sum\\limits_{j=1}^{k}y^i_j\\log{\\tilde{y}^i_j}, \\tag{1}\n",
"$$\n",
"\n",
"其中 $\\mathbf{W}$ 和 $\\mathbf{b}$ 是经典 FCNN 的权重(weight)和偏置(bias)。注意这个损失函数是由交叉熵(cross-entropy)[2] 推导得到的。\n",
"\n",
"### 方案流程 \n",
"\n",
"![pipeline](./figures/vsql-fig-pipeline-cn.png \"图1:VSQL 的流程图\")\n",
"<div style=\"text-align:center\">图1:VSQL 的流程图 </div>\n",
"\n",
"这里我们给出实现 VSQL 的流程。\n",
"\n",
"1. 将经典数据 $\\mathbf{x}^i$ 编码到量子态 $\\left|\\mathbf{x}^i\\right>$。\n",
"2. 准备一个参数化局部量子电路 $U(\\mathbf{\\theta})$ 并且初始化它的参数 $\\mathbf{\\theta}$。\n",
"3. 在前几个量子比特上作用 $U(\\mathbf{\\theta})$,然后通过测量局部可观测量(比如说泡利 $X\\otimes X\\cdots \\otimes X$ 算符)来获取一个局部影子特征。\n",
"4. 每次将 $U(\\mathbf{\\theta})$ 向下移动一个量子比特,重复步骤3直到 $U(\\mathbf{\\theta})$ 作用到最后一个量子比特上。\n",
"5. 将步骤3–4中得到的所有局部影子特征传入经典 FCNN 并通过激活函数得到预测的标签 $\\tilde{\\mathbf{y}}^i$。对于多分类问题来说,我们使用归一化指数函数 (softmax) 作为激活函数。\n",
"6. 重复步骤3–5直到数据集内所有的数据点都经过了处理。然后计算损失函数 $\\mathcal{L}(\\mathbf{\\theta}, \\mathbf{W}, \\mathbf{b})$。\n",
"7. 通过梯度下降等优化方法调整参数 $\\mathbf{\\theta}$、$\\mathbf{W}$ 和 $\\mathbf{b}$ 的值,从而最小化损失函数。这样我们就得到了优化后的模型 $\\mathcal{F}$。\n",
"\n",
"由于 VSQL 只获取局部影子特征,所以它可以比较容易地在有拓扑连接限制的量子设备上实现。除此之外,因为我们用同一个 $U(\\mathbf{\\theta})$ 来获取整个电路上的局部影子特征,所以需要训练的参数数量相对于通常使用的变分量子分类器来说大大减少。"
]
},
{
"cell_type": "markdown",
"id": "attempted-ticket",
"metadata": {},
"source": [
"## Paddle Quantum 实现\n",
"\n",
"接下来,我们将用 VSQL 来完成手写数字图像二分类的问题。我们使用的数据来源于常用于基准测试的公开数据集 MNIST [3],其中包含了标签为从 '0' 到 '9' 的十个类别的数据。为了便于展示,我们这里只考虑二分类问题,使用标签为 '0' 和 '1' 的数据。 \n",
"\n",
"首先,导入所需要的语言包:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "senior-blues",
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"import numpy as np\n",
"import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle.vision.datasets import MNIST\n",
"import paddle.nn.functional as F\n",
"\n",
"paddle.set_default_dtype(\"float64\")"
]
},
{
"cell_type": "markdown",
"id": "korean-beverage",
"metadata": {},
"source": [
"### 数据的预处理\n",
"\n",
"每个手写数字图像都是由 $28\\times 28$ 个取值在 $[0, 255]$ 之间的灰度像素点组成。我们需要先把这个 $28\\times 28$ 的二维矩阵转化为一个长度为784的一维向量 $\\mathbf{x}^i$,然后再使用振幅编码将每个 $\\mathbf{x}^i$ 编码到有10个量子比特的量子态 $\\left|\\mathbf{x}^i\\right>$。为了进行振幅编码,我们需要归一化每个向量,再在它的尾部补零使每个向量的长度与有10个量子比特的量子态一致。"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "surgical-breast",
"metadata": {},
"outputs": [],
"source": [
"# 归一化处理向量并在尾部补零\n",
"def norm_img(images):\n",
" new_images = [np.pad(np.array(i).flatten(), (0, 240), constant_values=(0, 0)) for i in images]\n",
" new_images = [paddle.to_tensor(i / np.linalg.norm(i), dtype='complex128') for i in new_images]\n",
" \n",
" return new_images"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "synthetic-holly",
"metadata": {},
"outputs": [],
"source": [
"def data_loading(n_train=1000, n_test=100):\n",
" # 我们使用 PaddlePaddle 提供的 MNIST\n",
" train_dataset = MNIST(mode='train')\n",
" test_dataset = MNIST(mode='test')\n",
" # 选出标签为0和1的数据点\n",
" train_dataset = np.array([i for i in train_dataset if i[1][0] == 0 or i[1][0] == 1], dtype=object)\n",
" test_dataset = np.array([i for i in test_dataset if i[1][0] == 0 or i[1][0] == 1], dtype=object)\n",
" np.random.shuffle(train_dataset)\n",
" np.random.shuffle(test_dataset)\n",
" # 将手写数字图像和标签分开\n",
" train_images = train_dataset[:, 0][:n_train]\n",
" train_labels = train_dataset[:, 1][:n_train].astype('int64')\n",
" test_images = test_dataset[:, 0][:n_test]\n",
" test_labels = test_dataset[:, 1][:n_test].astype('int64')\n",
" # 归一化向量并补零\n",
" x_train = norm_img(train_images)\n",
" x_test = norm_img(test_images)\n",
" # 将标签处理为独热向量\n",
" train_targets = np.array(train_labels).reshape(-1)\n",
" y_train = paddle.to_tensor(np.eye(2)[train_targets])\n",
" test_targets = np.array(test_labels).reshape(-1)\n",
" y_test = paddle.to_tensor(np.eye(2)[test_targets])\n",
" \n",
" return x_train, y_train, x_test, y_test"
]
},
{
"cell_type": "markdown",
"id": "dominant-hartford",
"metadata": {},
"source": [
"### 搭建局部影子电路\n",
"\n",
"接下来我们要搭建电路。在讲电路的细节之前,我们需要说明几个参数:\n",
"- $n$:编码后量子态的量子比特数目。\n",
"- $n_{qsc}$:量子影子电路的宽度。我们每次只在连续 $n_{qsc}$ 个量子比特上作用 $U(\\mathbf{\\theta})$。\n",
"- $D$:电路的深度,表示 $U(\\mathbf{\\theta})$ 门中某一层电路重复的次数。\n",
"\n",
"这里我们给出 $n=4$、$n_{qsc}=2$ 时的一个例子:\n",
"\n",
"我们首先在前两个量子比特上作用 $U(\\mathbf{\\theta})$,并且获取第一个影子特征 $O_1$。\n",
"\n",
"![qubit0](./figures/vsql-fig-qubit0-cn.png \"图2:获取第一个影子特征\")\n",
"<div style=\"text-align:center\">图2: 获取第一个影子特征 </div>\n",
"\n",
"然后我们准备一样的输入态 $\\left|\\mathbf{x}^i\\right>$,在中间两个量子比特上作用 $U(\\mathbf{\\theta})$,得到第二个影子特征 $O_2$。\n",
"\n",
"![qubit1](./figures/vsql-fig-qubit1-cn.png \"图3:获取第二个影子特征\")\n",
"<div style=\"text-align:center\">图3: 获取第二个影子特征 </div>\n",
"\n",
"最后,我们再准备一个一样的输入态,在最后两个量子比特上作用 $U(\\mathbf{\\theta})$,得到影子特征 $O_3$。这样我们就处理完了这个数据点!\n",
"\n",
"![qubit2](./figures/vsql-fig-qubit2-cn.png \"图4:获取第三个影子特征\")\n",
"<div style=\"text-align:center\">图4: 获取第三个影子特征 </div>\n",
"\n",
"通常来说,处理一个数据点需要重复以上步骤 $n - n_{qsc} + 1$ 次。有一点需要指出的是,在上面这个例子中我们只使用了一个影子电路,在获取这三个影子特征时我们使用同样的参数 $\\mathbf{\\theta}$。你可以选择增加影子电路的数量来解决更复杂的问题,这里需要注意的是不同影子电路中的参数 $\\mathbf{\\theta}$ 不同。 \n",
" \n",
"在后面的 MNIST 二分类任务中,我们将使用2–局部影子电路,即 $n_{qsc}=2$。图5展示了这个影子电路的结构。\n",
"\n",
"![2-local](./figures/vsql-fig-2-local.png \"图5:$n_{qsc}=2$ 时 $U(\\mathbf{\\theta})$ 的结构\")\n",
"<div style=\"text-align:center\">图5:$n_{qsc}=2$ 时 $U(\\mathbf{\\theta})$ 的结构</div>\n",
"\n",
"为了增强量子电路的表达能力,我们将重复 $D$ 次虚线框中的结构。$U(\\mathbf{\\theta})$ 的设计并不是唯一的,这里展示的仅仅是一个例子,读者不妨尝试设计自己的电路结构。"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "orange-american",
"metadata": {},
"outputs": [],
"source": [
"# 搭建 U(theta)\n",
"def U_theta(theta, n, n_start, n_qsc=2, depth=1):\n",
" # 初始化电路\n",
" cir = UAnsatz(n)\n",
" # 先搭建广义的旋转层\n",
" for i in range(n_qsc):\n",
" cir.rx(theta[0][0][i], n_start + i)\n",
" cir.ry(theta[0][1][i], n_start + i)\n",
" cir.rx(theta[0][2][i], n_start + i)\n",
" # 搭建纠缠层和 Ry 旋转层,重复 D 次\n",
" for repeat in range(1, depth + 1):\n",
" for i in range(n_qsc - 1):\n",
" cir.cnot([n_start + i, n_start + i + 1])\n",
" cir.cnot([n_start + n_qsc - 1, n_start])\n",
" for i in range(n_qsc):\n",
" cir.ry(theta[repeat][1][i], n_start + i)\n",
"\n",
" return cir"
]
},
{
"cell_type": "markdown",
"id": "scientific-agreement",
"metadata": {},
"source": [
"当 $n_{qsc}$ 比较大的时候,我们可以通过对上述的2–局部影子电路进行扩展来搭建 $n_{qsc}$–局部影子电路。我们可以打印一个深度为2的4–局部影子电路来看看这种扩展是怎么进行的:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "shaped-location",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--Rx(1.591)----Ry(1.112)----Rx(1.673)----*--------------X----Ry(2.861)----*--------------X----Ry(3.252)--\n",
" | | | | \n",
"--Rx(1.569)----Ry(0.516)----Rx(3.077)----X----*---------|----Ry(4.816)----X----*---------|----Ry(3.264)--\n",
" | | | | \n",
"--Rx(0.560)----Ry(6.122)----Rx(1.436)---------X----*----|----Ry(6.038)---------X----*----|----Ry(2.531)--\n",
" | | | | \n",
"--Rx(1.425)----Ry(1.378)----Rx(5.048)--------------X----*----Ry(5.986)--------------X----*----Ry(1.309)--\n",
" \n",
"---------------------------------------------------------------------------------------------------------\n",
" \n",
"---------------------------------------------------------------------------------------------------------\n",
" \n"
]
}
],
"source": [
"N = 6\n",
"NSTART = 0\n",
"NQSC = 4\n",
"D = 2\n",
"theta = paddle.uniform([D + 1, 3, NQSC], min=0.0, max=2 * np.pi)\n",
"cir = U_theta(theta, N, NSTART, n_qsc=NQSC, depth=D)\n",
"print(cir)"
]
},
{
"cell_type": "markdown",
"id": "continued-february",
"metadata": {},
"source": [
"### 影子特征\n",
"\n",
"在前面的教程中,我们多次提到影子特征,那么究竟什么是影子特征呢?我们可以认为它是一个从希尔伯特空间到经典空间的投影。有非常多这样的投影都可以作为影子特征。这里我们将在 $n_{qsc}$ 个量子比特上用泡利 $X\\otimes X\\otimes \\cdots \\otimes X$ 算符进行测量得到的期望值作为影子特征。在我们前面举的 $n=4$ 的例子中,在前两个量子比特上测量得到的 $O_1 = \\left<X\\otimes X\\right>$ 就是我们用影子电路获取的第一个影子特征。"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "advanced-clinic",
"metadata": {},
"outputs": [],
"source": [
"# 构造用来获取影子特征的可观测量\n",
"def observable(n_start, n_qsc=2):\n",
" pauli_str = ','.join('x' + str(i) for i in range(n_start, n_start + n_qsc))\n",
" \n",
" return [[1.0, pauli_str]]"
]
},
{
"cell_type": "markdown",
"id": "handled-halloween",
"metadata": {},
"source": [
"### 用 FCNN 进行经典后处理\n",
"\n",
"我们将获得的所有影子特征传入一个经典的 FCNN,并使用归一化指数函数作为激活函数。经过归一化指数函数后得到的输出是一个概率分布,输出中的第 $i$ 个元素代表这个数据点属于第 $i$ 类的概率,我们认为预测的类别就是输出中概率最高的类别。为了提高预测的准确率,我们将预测标签和实际标签之间的累计差距作为损失函数进行优化:\n",
"\n",
"$$\n",
"\\mathcal{L}(\\mathbf{\\theta}, \\mathbf{W}, \\mathbf{b}) = -\\frac{1}{N}\\sum\\limits_{i=1}^{N}\\sum\\limits_{j=1}^{k}y^i_j\\log{\\tilde{y}^i_j}.\\tag{2}\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "certified-details",
"metadata": {},
"outputs": [],
"source": [
"class Net(paddle.nn.Layer):\n",
" def __init__(self,\n",
" n, # 全局量子比特的数量: n \n",
" n_qsc, # 影子电路的宽度\n",
" depth=1, # 电路深度\n",
" seed=3, # 随机数种子\n",
" ):\n",
" super(Net, self).__init__()\n",
"\n",
" self.n = n\n",
" self.n_qsc = n_qsc\n",
" self.depth = depth\n",
" # 初始化参数列表 theta,并用 [0, 2*pi] 的均匀分布来填充初始值\n",
" self.theta = self.create_parameter(shape=[depth + 1, 3, n_qsc],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi))\n",
" # FCNN, 采用高斯分布来初始化权重和偏置\n",
" self.fc = paddle.nn.Linear(n - n_qsc + 1, 2,\n",
" weight_attr=paddle.ParamAttr(initializer=paddle.nn.initializer.Normal()),\n",
" bias_attr=paddle.ParamAttr(initializer=paddle.nn.initializer.Normal()))\n",
" \n",
" # 定义前向传播机制、计算损失函数 和交叉验证正确率\n",
" def forward(self, batch_in, label):\n",
" # 量子部分\n",
" dim = len(batch_in)\n",
" features = []\n",
" for state in batch_in:\n",
" f_i = []\n",
" for st in range(self.n - self.n_qsc + 1):\n",
" ob = observable(st, n_qsc=self.n_qsc)\n",
" cir = U_theta(self.theta, self.n, st, n_qsc=self.n_qsc)\n",
" cir.run_state_vector(state)\n",
" # 计算期望值\n",
" f_ij = cir.expecval(ob)\n",
" f_i.append(f_ij)\n",
" f_i = paddle.concat(f_i)\n",
" features.append(f_i)\n",
" features = paddle.stack(features)\n",
" # 经典部分\n",
" outputs = self.fc(features)\n",
" outputs = F.log_softmax(outputs)\n",
" # 计算损失函数和准确率\n",
" loss = -paddle.mean(paddle.sum(outputs * label)) \n",
" is_correct = 0\n",
" for i in range(dim):\n",
" if paddle.argmax(label[i], axis=-1) == paddle.argmax(outputs[i], axis=-1):\n",
" is_correct = is_correct + 1\n",
" acc = is_correct / dim\n",
" \n",
" return loss, acc"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "classified-saying",
"metadata": {},
"outputs": [],
"source": [
"def ShadowClassifier(N=4, n_qsc=2, D=1, EPOCH=4, LR=0.1, BATCH=1, seed=1, N_train=1000, N_test=100):\n",
" # 加载数据\n",
" x_train, y_train, x_test, y_test = data_loading(n_train=N_train, n_test=N_test)\n",
" # 初始化神经网络\n",
" net = Net(N, n_qsc, depth=D, seed=seed)\n",
" # 一般来说,我们利用 Adam 优化器来获得相对好的收敛\n",
" # 当然你可以改成 SGD 或者是 RMSprop\n",
" opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"\n",
" # 优化循环\n",
" for ep in range(EPOCH):\n",
" for itr in range(N_train // BATCH):\n",
" # 前向传播计算损失函数和准确率\n",
" loss, batch_acc = net(x_train[itr * BATCH:(itr + 1) * BATCH],\n",
" y_train[itr * BATCH:(itr + 1) * BATCH])\n",
" # 反向传播极小化损失函数\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" opt.clear_grad()\n",
" # 在测试集上测试\n",
" if itr % 10 == 0:\n",
" # 计算测试集上的正确率 test_acc\n",
" loss_useless, test_acc = net(x_test[0:N_test],\n",
" y_test[0:N_test])\n",
" # 打印测试结果\n",
" print(\"epoch:%3d\" % ep, \" iter:%3d\" % itr,\n",
" \" loss: %.4f\" % loss.numpy(),\n",
" \" batch acc: %.4f\" % batch_acc,\n",
" \" test acc: %.4f\" % test_acc)"
]
},
{
"cell_type": "markdown",
"id": "passing-diagram",
"metadata": {},
"source": [
"接下来我们来看看实际的训练效果,整个训练过程大概需要八分钟:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "chicken-trash",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"epoch: 0 iter: 0 loss: 13.1132 batch acc: 0.6000 test acc: 0.5900\n",
"epoch: 0 iter: 10 loss: 11.3892 batch acc: 0.9000 test acc: 0.9600\n",
"epoch: 0 iter: 20 loss: 8.4291 batch acc: 0.9500 test acc: 0.9700\n",
"epoch: 1 iter: 0 loss: 8.3585 batch acc: 0.9000 test acc: 0.9700\n",
"epoch: 1 iter: 10 loss: 6.9244 batch acc: 0.9500 test acc: 0.9800\n",
"epoch: 1 iter: 20 loss: 6.0455 batch acc: 0.9500 test acc: 0.9800\n",
"epoch: 2 iter: 0 loss: 5.4859 batch acc: 0.9500 test acc: 0.9800\n",
"epoch: 2 iter: 10 loss: 5.1867 batch acc: 0.9500 test acc: 0.9800\n",
"epoch: 2 iter: 20 loss: 5.3668 batch acc: 0.9500 test acc: 0.9700\n",
"time used: 551.4094610214233\n"
]
}
],
"source": [
"time_st = time.time()\n",
"ShadowClassifier(\n",
" N=10, # 全局量子比特的数量: n \n",
" n_qsc=2, # 影子电路的宽度\n",
" D=1, # 采用的电路深度\n",
" EPOCH=3, # 训练 epoch 轮数\n",
" LR=0.02, # 设置学习速率\n",
" BATCH=20, # 训练时 batch 的大小\n",
" seed=1024, # 随机数种子\n",
" N_train=500, # 规定训练集大小\n",
" N_test=100 # 规定测试集大小\n",
")\n",
"print(\"time used:\", time.time() - time_st)"
]
},
{
"cell_type": "markdown",
"id": "second-placement",
"metadata": {},
"source": [
"## 总结\n",
"\n",
"VSQL 是一个基于经典影子的量子–经典混合算法,它以卷积的方式获取局部影子特征。VSQL 结合了参数化量子电路 $U(\\mathbf{\\theta})$ 和经典 FCNN,在二分类任务中表现出色。在[量子分类器](./QClassifier_CN.ipynb)的教程里,我们介绍了一种常用的使用参数化量子电路的分类器。这种分类器在所有的量子比特上作用参数化电路,所以优化器必须搜索整个希尔伯特空间来找到最优的 $\\mathbf{\\theta}$。和这种方法不同的是,VSQL 每次只在少量选中的量子比特上作用参数化局部量子电路 $U(\\mathbf{\\theta})$。对于一个 $k$ 分类问题来说,VSQL 需要训练的是参数化局部量子电路中的参数和经典 FCNN 中的参数,加在一起总共是 $n_{qsc}D + [(n-n_{qsc}+1)+1]k$ 个参数。我们可以看到,和常用的变分量子分类器需要训练的参数个数 $nD$ 比起来,VSQL 参数化局部量子电路部分需要训练的参数数量 $n_{qsc}D$ 大大减少,也就是说,VSQL 需要的量子资源大大减少。"
]
},
{
"cell_type": "markdown",
"id": "nonprofit-motel",
"metadata": {},
"source": [
"---\n",
"\n",
"## 参考文献\n",
"\n",
"[1] Li, Guangxi, et al. \"VSQL: Variational Shadow Quantum Learning for Classification.\" [arXiv:2012.08288 (2020).](https://arxiv.org/abs/2012.08288)\n",
"\n",
"[2] Goodfellow, Ian, et al. Deep learning. Vol. 1. No. 2. Cambridge: MIT press, 2016.\n",
"\n",
"[3] LeCun, Yann. \"The MNIST database of handwritten digits.\" http://yann.lecun.com/exdb/mnist/ (1998)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 5
}
{
"cells": [
{
"cell_type": "markdown",
"id": "adjacent-printing",
"metadata": {},
"source": [
"# Variational Shadow Quantum Learning\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"id": "rising-daisy",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"In this tutorial, we will discuss the workflow of Variational Shadow Quantum Learning (VSQL) [1] and accomplish a **binary classification** task using VSQL. VSQL is a hybird quantum-classical framework for supervised quantum learning, which utilizes parameterized quantum circuits and classical shadows. Unlike commonly used variational quantum algorithms, the VSQL method extracts \"local\" features from the subspace instead of the whole Hilbert space.\n",
"\n",
"### Background\n",
"\n",
"We consider a $k$-label classification problem. The input is a set containing $N$ labeled data points $D=\\left\\{(\\mathbf{x}^i, \\mathbf{y}^i)\\right\\}_{i=1}^{N}$, where $\\mathbf{x}^i\\in\\mathbb{R}^{m}$ is the data point and $\\mathbf{y}^i$ is a one-hot vector with length $k$ indicating which category the corresponding data point belongs to. Representing the labels as one-hot vectors is a common choice within the machine learning community. For example, for $k=3$, $\\mathbf{y}^{a}=[1, 0, 0]^\\text{T}, \\mathbf{y}^{b}=[0, 1, 0]^\\text{T}$, and $\\mathbf{y}^{c}=[0, 0, 1]^\\text{T}$ indicate that the $a^{\\text{th}}$, the $b^{\\text{th}}$, and the $c^{\\text{th}}$ data points belong to class 0, class 1, and class 2, respectively. **The learning process aims to train a model $\\mathcal{F}$ to predict the label of every data point as accurately as possible.**\n",
"\n",
"The realization of $\\mathcal{F}$ in VSQL is a combination of parameterized local quantum circuits, known as **shadow circuits**, and a classical fully-connected neural network (FCNN). VSQL requires preprocessing to encode classical information into quantum states. After encoding the data, we convolutionally apply a parameterized local quantum circuit $U(\\mathbf{\\theta})$ to qubits in each encoded quantum state, where $\\mathbf{\\theta}$ is the vector of parameters in the circuit. Then, expectation values are obtained via measuring local observables on these qubits. After the measurement, there is an additional classical FCNN for postprocessing.\n",
"\n",
"We can write the output of $\\mathcal{F}$, which is obtained from VSQL, as $\\tilde{\\mathbf{y}}^i = \\mathcal{F}(\\mathbf{x}^i)$. Here $\\tilde{\\mathbf{y}}^i$ is a probability distribution, where $\\tilde{y}^i_j$ is the probability of the $i^{\\text{th}}$ data point belonging to the $j^{\\text{th}}$ class. In order to predict the actual label, we calculate the cumulative distance between $\\tilde{\\mathbf{y}}^i$ and $\\mathbf{y}^i$ as the loss function $\\mathcal{L}$ to be optimized:\n",
"\n",
"$$\n",
"\\mathcal{L}(\\mathbf{\\theta}, \\mathbf{W}, \\mathbf{b}) = -\\frac{1}{N}\\sum\\limits_{i=1}^{N}\\sum\\limits_{j=1}^{k}y^i_j\\log{\\tilde{y}^i_j}, \\tag{1}\n",
"$$\n",
"\n",
"where $\\mathbf{W}$ and $\\mathbf{b}$ are the weights and the bias of the one layer FCNN. Note that this loss function is derived from cross-entropy [2].\n",
"\n",
"### Pipeline\n",
"\n",
"![pipeline](./figures/vsql-fig-pipeline.png \"Figure 1: Flow chart of VSQL\")\n",
"<div style=\"text-align:center\">Figure 1: Flow chart of VSQL </div>\n",
"\n",
"Here we give the whole pipeline to implement VSQL.\n",
"\n",
"1. Encode a classical data point $\\mathbf{x}^i$ into a quantum state $\\left|\\mathbf{x}^i\\right>$.\n",
"2. Prepare a parameterized local quantum circuit $U(\\mathbf{\\theta})$ and initialize its parameters $\\mathbf{\\theta}$.\n",
"3. Apply $U(\\mathbf{\\theta})$ on the first few qubits. Then, obtain a shadow feature via measuring a local observable, for instance, $X\\otimes X\\cdots \\otimes X$, on these qubits.\n",
"4. Sliding down $U(\\mathbf{\\theta})$ one qubit each time, repeat step 3 until the last qubit has been covered.\n",
"5. Feed all shadow features obtained from steps 3-4 to an FCNN and get the predicted label $\\tilde{\\mathbf{y}}^i$ through an activation function. For multi-label classification problems, we use the softmax activation function.\n",
"5. Repeat steps 3-5 until all data points in the data set have been processed. Then calculate the loss function $\\mathcal{L}(\\mathbf{\\theta}, \\mathbf{W}, \\mathbf{b})$.\n",
"6. Adjust the parameters $\\mathbf{\\theta}$, $\\mathbf{W}$, and $\\mathbf{b}$ through optimization methods such as gradient descent to minimize the loss function. Then we get the optimized model $\\mathcal{F}$.\n",
"\n",
"Since VSQL only extracts local shadow features, it can be easily implemented on quantum devices with topological connectivity limits. Besides, since the $U(\\mathbf{\\theta})$ used in circuits are identical, the number of parameters involved is significantly smaller than other commonly used variational quantum classifiers."
]
},
{
"cell_type": "markdown",
"id": "after-shadow",
"metadata": {},
"source": [
"## Paddle Quantum Implementation\n",
"\n",
"We will apply VSQL to classify handwritten digits taken from the MNIST dataset [3], a public benchmark dataset containing ten different classes labeled from '0' to '9'. Here, we consider a binary classification problem for the prupose of demonstration, in which only data labeled as '0' or '1' are used.\n",
"\n",
"First, we import the required packages."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "auburn-compound",
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"import numpy as np\n",
"import paddle\n",
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle.vision.datasets import MNIST\n",
"import paddle.nn.functional as F\n",
"\n",
"paddle.set_default_dtype(\"float64\")"
]
},
{
"cell_type": "markdown",
"id": "violent-procurement",
"metadata": {},
"source": [
"### Data preprocessing\n",
"\n",
"Each image of a handwritten digit consists of $28\\times 28$ grayscale pixels valued in $[0, 255]$. We first flatten the $28\\times 28$ 2D matrix into a 1D vector $\\mathbf{x}^i$, and use amplitude encoding to encode every $\\mathbf{x}^i$ into a 10-qubit quantum state $\\left|\\mathbf{x}^i\\right>$. To do amplitude encoding, we first normalize each vector and pad it with zeros at the end."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "valuable-criterion",
"metadata": {},
"outputs": [],
"source": [
"# Normalize the vector and do zero-padding\n",
"def norm_img(images):\n",
" new_images = [np.pad(np.array(i).flatten(), (0, 240), constant_values=(0, 0)) for i in images]\n",
" new_images = [paddle.to_tensor(i / np.linalg.norm(i), dtype='complex128') for i in new_images]\n",
" \n",
" return new_images"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "ancient-philosophy",
"metadata": {},
"outputs": [],
"source": [
"def data_loading(n_train=1000, n_test=100):\n",
" # We use the MNIST provided by paddle\n",
" train_dataset = MNIST(mode='train')\n",
" test_dataset = MNIST(mode='test')\n",
" # Select data points from category 0 and 1\n",
" train_dataset = np.array([i for i in train_dataset if i[1][0] == 0 or i[1][0] == 1], dtype=object)\n",
" test_dataset = np.array([i for i in test_dataset if i[1][0] == 0 or i[1][0] == 1], dtype=object)\n",
" np.random.shuffle(train_dataset)\n",
" np.random.shuffle(test_dataset)\n",
" # Separate images and labels\n",
" train_images = train_dataset[:, 0][:n_train]\n",
" train_labels = train_dataset[:, 1][:n_train].astype('int64')\n",
" test_images = test_dataset[:, 0][:n_test]\n",
" test_labels = test_dataset[:, 1][:n_test].astype('int64')\n",
" # Normalize data and pad them with zeros\n",
" x_train = norm_img(train_images)\n",
" x_test = norm_img(test_images)\n",
" # Transform integer labels into one-hot vectors\n",
" train_targets = np.array(train_labels).reshape(-1)\n",
" y_train = paddle.to_tensor(np.eye(2)[train_targets])\n",
" test_targets = np.array(test_labels).reshape(-1)\n",
" y_test = paddle.to_tensor(np.eye(2)[test_targets])\n",
" \n",
" return x_train, y_train, x_test, y_test"
]
},
{
"cell_type": "markdown",
"id": "alive-spanish",
"metadata": {},
"source": [
"### Building the shadow circuit\n",
"\n",
"Now, we are ready for the next step. Before diving into details of the circuit, we need to clarify several parameters:\n",
"- $n$: the number of qubits encoding each data point.\n",
"- $n_{qsc}$: the width of the quantum shadow circuit . We only apply $U(\\mathbf{\\theta})$ on consecutive $n_{qsc}$ qubits each time.\n",
"- $D$: the depth of the circuit, indicating the repeating times of a layer in $U(\\mathbf{\\theta})$.\n",
"\n",
"Here, we give an example where $n = 4$ and $n_{qsc} = 2$.\n",
"\n",
"We first apply $U(\\mathbf{\\theta})$ to the first two qubits and obtain the shadow feature $O_1$.\n",
"\n",
"![qubit0](./figures/vsql-fig-qubit0.png \"Figure 2: The first circuit\")\n",
"<div style=\"text-align:center\">Figure 2: The first circuit </div>\n",
"\n",
"Then, we prepare a copy of the same input state $\\left|\\mathbf{x}^i\\right>$, apply $U(\\mathbf{\\theta})$ to the two qubits in the middle, and obtain the shadow feature $O_2$.\n",
"\n",
"![qubit1](./figures/vsql-fig-qubit1.png \"Figure 3: The second circuit\")\n",
"<div style=\"text-align:center\">Figure 3: The second circuit </div>\n",
"\n",
"Finally, we prepare another copy of the same input state, apply $U(\\mathbf{\\theta})$ to the last two qubits, and obtain the shadow feature $O_3$. Now we are done with this data point!\n",
"\n",
"![qubit2](./figures/vsql-fig-qubit2.png \"Figure 4: The last circuit\")\n",
"<div style=\"text-align:center\">Figure 4: The last circuit </div>\n",
"\n",
"In general, we will need to repeat this process for $n - n_{qsc} + 1$ times for each data point. One thing to point out is that we only use one shadow circuit in the above example. When sliding the shadow circuit $U(\\mathbf{\\theta})$ through the $n$-qubit Hilbert space, the same parameters $\\mathbf{\\theta}$ are used. You can use more shadow circuits for complicated tasks, and different shadow circuits should have different parameters $\\mathbf{\\theta}$.\n",
"\n",
"Below, we will use a 2-local shadow circuit, i.e., $n_{qsc}=2$ for the MNIST classification task, and the circuit's structure is shown in Figure 5.\n",
"\n",
"![2-local](./figures/vsql-fig-2-local.png \"Figure 5: The 2-local shadow circuit design\")\n",
"<div style=\"text-align:center\">Figure 5: The 2-local shadow circuit design </div>\n",
"\n",
"The circuit layer in the dashed box is repeated for $D$ times to increase the expressive power of the quantum circuit. The structure of the circuit is not unique. You can try to design your own circuit."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "derived-workstation",
"metadata": {},
"outputs": [],
"source": [
"# Construct the shadow circuit U(theta)\n",
"def U_theta(theta, n, n_start, n_qsc=2, depth=1):\n",
" # Initialize the circuit\n",
" cir = UAnsatz(n)\n",
" # Add layers of rotation gates\n",
" for i in range(n_qsc):\n",
" cir.rx(theta[0][0][i], n_start + i)\n",
" cir.ry(theta[0][1][i], n_start + i)\n",
" cir.rx(theta[0][2][i], n_start + i)\n",
" # Add D layers of the dashed box\n",
" for repeat in range(1, depth + 1):\n",
" for i in range(n_qsc - 1):\n",
" cir.cnot([n_start + i, n_start + i + 1])\n",
" cir.cnot([n_start + n_qsc - 1, n_start])\n",
" for i in range(n_qsc):\n",
" cir.ry(theta[repeat][1][i], n_start + i)\n",
"\n",
" return cir"
]
},
{
"cell_type": "markdown",
"id": "constant-scottish",
"metadata": {},
"source": [
"When $n_{qsc}$ is larger, the $n_{qsc}$-local shadow circuit can be constructed by extending this 2-local shadow circuit. Let's print a 4-local shadow circuit with $D=2$ to find out how it works."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "roman-radical",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--Rx(2.435)----Ry(5.433)----Rx(5.893)----*--------------X----Ry(0.430)----*--------------X----Ry(3.016)--\n",
" | | | | \n",
"--Rx(4.804)----Ry(2.413)----Rx(4.271)----X----*---------|----Ry(3.770)----X----*---------|----Ry(4.303)--\n",
" | | | | \n",
"--Rx(1.397)----Ry(0.021)----Rx(2.358)---------X----*----|----Ry(5.194)---------X----*----|----Ry(0.938)--\n",
" | | | | \n",
"--Rx(2.457)----Ry(0.133)----Rx(0.743)--------------X----*----Ry(2.042)--------------X----*----Ry(3.704)--\n",
" \n",
"---------------------------------------------------------------------------------------------------------\n",
" \n",
"---------------------------------------------------------------------------------------------------------\n",
" \n"
]
}
],
"source": [
"N = 6\n",
"NSTART = 0\n",
"NQSC = 4\n",
"D = 2\n",
"theta = paddle.uniform([D + 1, 3, NQSC], min=0.0, max=2 * np.pi)\n",
"cir = U_theta(theta, N, NSTART, n_qsc=NQSC, depth=D)\n",
"print(cir)"
]
},
{
"cell_type": "markdown",
"id": "extreme-abuse",
"metadata": {},
"source": [
"### Shadow features\n",
"\n",
"We've talked a lot about shadow features, but what is a shadow feature? It can be seen as a projection of a state from Hilbert space to classical space. There are various projections that can be used as a shadow feature. Here, we choose the expectation value of the Pauli $X\\otimes X\\otimes \\cdots \\otimes X$ observable on selected $n_{qsc}$ qubits as the shadow feature. In our previous example, $O_1 = \\left<X\\otimes X\\right>$ on the first two qubits is the first shadow feature we extracted with the shadow circuit."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "equipped-begin",
"metadata": {},
"outputs": [],
"source": [
"# Construct the observable for extracting shadow features\n",
"def observable(n_start, n_qsc=2):\n",
" pauli_str = ','.join('x' + str(i) for i in range(n_start, n_start + n_qsc))\n",
" \n",
" return [[1.0, pauli_str]]"
]
},
{
"cell_type": "markdown",
"id": "exempt-brooks",
"metadata": {},
"source": [
"### Classical postprocessing with FCNN\n",
"\n",
"After obtaining all shadow features, we feed them into a classical FCNN. We use the softmax activation function so that the output from the FCNN will be a probability distribution. The $i^{\\text{th}}$ element of the output is the probability of this data point belonging to the $i^{\\text{th}}$ category, and we predict this data point belongs to the category with the highest probability. In order to predict the actual label, we calculate the cumulative distance between the predicted label and the actual label as the loss function to be optimized:\n",
"\n",
"$$\n",
"\\mathcal{L}(\\mathbf{\\theta}, \\mathbf{W}, \\mathbf{b}) = -\\frac{1}{N}\\sum\\limits_{i=1}^{N}\\sum\\limits_{j=1}^{k}y^i_j\\log{\\tilde{y}^i_j}. \\tag{2}\n",
"$$ "
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "upper-petite",
"metadata": {},
"outputs": [],
"source": [
"class Net(paddle.nn.Layer):\n",
" def __init__(self,\n",
" n, # Number of qubits: n \n",
" n_qsc, # Number of local qubits in a shadow\n",
" depth=1, # Circuit depth\n",
" seed=3, # Random seed\n",
" ):\n",
" super(Net, self).__init__()\n",
"\n",
" self.n = n\n",
" self.n_qsc = n_qsc\n",
" self.depth = depth\n",
" # Initialize the parameters theta with a uniform distribution of [0, 2 * pi]\n",
" self.theta = self.create_parameter(shape=[depth + 1, 3, n_qsc],\n",
" default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2 * np.pi))\n",
" # FCNN, initialize the weights and the bias with a Gaussian distribution\n",
" self.fc = paddle.nn.Linear(n - n_qsc + 1, 2,\n",
" weight_attr=paddle.ParamAttr(initializer=paddle.nn.initializer.Normal()),\n",
" bias_attr=paddle.ParamAttr(initializer=paddle.nn.initializer.Normal()))\n",
" \n",
" # Define forward propagation mechanism, and then calculate loss function and cross-validation accuracy\n",
" def forward(self, batch_in, label):\n",
" # Quantum part\n",
" dim = len(batch_in)\n",
" features = []\n",
" for state in batch_in:\n",
" f_i = []\n",
" for st in range(self.n - self.n_qsc + 1):\n",
" ob = observable(st, n_qsc=self.n_qsc)\n",
" cir = U_theta(self.theta, self.n, st, n_qsc=self.n_qsc)\n",
" cir.run_state_vector(state)\n",
" # Calculate the expectation value\n",
" f_ij = cir.expecval(ob)\n",
" f_i.append(f_ij)\n",
" f_i = paddle.concat(f_i)\n",
" features.append(f_i)\n",
" features = paddle.stack(features)\n",
" # Classical part\n",
" outputs = self.fc(features)\n",
" outputs = F.log_softmax(outputs)\n",
" # Calculate loss and accuracy\n",
" loss = -paddle.mean(paddle.sum(outputs * label)) \n",
" is_correct = 0\n",
" for i in range(dim):\n",
" if paddle.argmax(label[i], axis=-1) == paddle.argmax(outputs[i], axis=-1):\n",
" is_correct = is_correct + 1\n",
" acc = is_correct / dim\n",
" \n",
" return loss, acc"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "handed-study",
"metadata": {},
"outputs": [],
"source": [
"def ShadowClassifier(N=4, n_qsc=2, D=1, EPOCH=4, LR=0.1, BATCH=1, seed=1, N_train=1000, N_test=100):\n",
" # Load data\n",
" x_train, y_train, x_test, y_test = data_loading(n_train=N_train, n_test=N_test)\n",
" # Initialize the neural network\n",
" net = Net(N, n_qsc, depth=D, seed=seed)\n",
" # Generally speaking, we use Adam optimizer to obtain relatively good convergence,\n",
" # You can change it to SGD or RMS prop.\n",
" opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())\n",
"\n",
" # Optimization loop\n",
" for ep in range(EPOCH):\n",
" for itr in range(N_train // BATCH):\n",
" # Forward propagation to calculate loss and accuracy\n",
" loss, batch_acc = net(x_train[itr * BATCH:(itr + 1) * BATCH],\n",
" y_train[itr * BATCH:(itr + 1) * BATCH])\n",
" # Use back propagation to minimize the loss function\n",
" loss.backward()\n",
" opt.minimize(loss)\n",
" opt.clear_grad()\n",
" # Evaluation\n",
" if itr % 10 == 0:\n",
" # Compute test accuracy and loss\n",
" loss_useless, test_acc = net(x_test[0:N_test],\n",
" y_test[0:N_test])\n",
" # Print test results\n",
" print(\"epoch:%3d\" % ep, \" iter:%3d\" % itr,\n",
" \" loss: %.4f\" % loss.numpy(),\n",
" \" batch acc: %.4f\" % batch_acc,\n",
" \" test acc: %.4f\" % test_acc)"
]
},
{
"cell_type": "markdown",
"id": "diverse-publisher",
"metadata": {},
"source": [
"Let's take a look at the actual training process, which takes about eight minutes: "
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "unique-indie",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"epoch: 0 iter: 0 loss: 18.4158 batch acc: 0.2500 test acc: 0.4800\n",
"epoch: 0 iter: 10 loss: 10.6799 batch acc: 0.8000 test acc: 0.9500\n",
"epoch: 0 iter: 20 loss: 10.1750 batch acc: 0.8500 test acc: 0.9400\n",
"epoch: 1 iter: 0 loss: 8.5254 batch acc: 0.9000 test acc: 0.9600\n",
"epoch: 1 iter: 10 loss: 7.0151 batch acc: 0.9000 test acc: 0.9700\n",
"epoch: 1 iter: 20 loss: 7.5365 batch acc: 0.9000 test acc: 0.9700\n",
"epoch: 2 iter: 0 loss: 6.5155 batch acc: 0.8500 test acc: 0.9700\n",
"epoch: 2 iter: 10 loss: 5.5648 batch acc: 0.9500 test acc: 0.9800\n",
"epoch: 2 iter: 20 loss: 6.3797 batch acc: 0.9500 test acc: 0.9700\n",
"time used: 548.4337043762207\n"
]
}
],
"source": [
"time_st = time.time()\n",
"ShadowClassifier(\n",
" N=10, # Number of qubits: n\n",
" n_qsc=2, # Number of local qubits in a shadow: n_qsc\n",
" D=1, # Circuit depth\n",
" EPOCH=3, # Number of training epochs\n",
" LR=0.02, # Learning rate\n",
" BATCH=20, # Batch size\n",
" seed=1024, # Random seed\n",
" N_train=500, # Number of training data\n",
" N_test=100 # Number of test data\n",
")\n",
"print(\"time used:\", time.time() - time_st)"
]
},
{
"cell_type": "markdown",
"id": "elegant-ability",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"VSQL is a hybrid quantum-classical algorithm based on classical shadows, which extracts local features in a convolution way. Combing parameterized circuit $U(\\mathbf{\\theta})$ with a classical FCNN, VSQL demonstrates a good performance in binary classification tasks. \n",
"In the [quantum classifier](./QClassifier_EN.ipynb) tutorial, we have introduced a commonly used classifier using a parameterized quantum circuit. In that framework, the parameterized circuit is applied to all qubits, and the optimization process searches through the whole Hilbert space to find the optimized $\\mathbf{\\theta}$. Unlike that method, in VSQL, the parameterized circuit $U(\\mathbf{\\theta})$ is only applied to a few selected qubits each time. The number of parameters of VSQL for $k$-label classification is the sum of parameters in $U(\\mathbf{\\theta})$ and parameters in FCNN, which is in total $n_{qsc}D + [(n-n_{qsc}+1)+1]k$. Compared to commonly used variational quantum classifiers that need $nD$ parameters in the parameterized quantum circuit, VSQL only has $n_{qsc}D$ parameters in the parameterized local quantum circuit. As a result, the amount of quantum resources (the number of quantum gates) required has been significantly reduced."
]
},
{
"cell_type": "markdown",
"id": "suitable-earthquake",
"metadata": {},
"source": [
"---\n",
"\n",
"## References\n",
"\n",
"[1] Li, Guangxi, et al. \"VSQL: Variational Shadow Quantum Learning for Classification.\" [arXiv:2012.08288 (2020).](https://arxiv.org/abs/2012.08288)\n",
"\n",
"[2] Goodfellow, Ian, et al. Deep learning. Vol. 1. No. 2. Cambridge: MIT press, 2016.\n",
"\n",
"[3] LeCun, Yann. \"The MNIST database of handwritten digits.\" http://yann.lecun.com/exdb/mnist/ (1998)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 5
}
因为 它太大了无法显示 source diff 。你可以改为 查看blob
因为 它太大了无法显示 source diff 。你可以改为 查看blob
......@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
"id": "7cebc922",
"id": "6a2df459",
"metadata": {},
"source": [
"# 在 Paddle Quantum 中模拟含噪量子电路\n",
......@@ -12,7 +12,7 @@
},
{
"cell_type": "markdown",
"id": "c2cf6d87",
"id": "d12197db",
"metadata": {},
"source": [
"## 噪声简介\n",
......@@ -79,7 +79,7 @@
},
{
"cell_type": "markdown",
"id": "aaa538b0",
"id": "84556435",
"metadata": {},
"source": [
"### Paddle Quantum 中添加信道的方式\n",
......@@ -90,7 +90,7 @@
{
"cell_type": "code",
"execution_count": 1,
"id": "689ef041",
"id": "ff3880f1",
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-08T05:16:08.247239Z",
......@@ -140,7 +140,7 @@
},
{
"cell_type": "markdown",
"id": "aec448b7",
"id": "863e4554",
"metadata": {},
"source": [
"之后,我们加上一个 $p=0.1$ 的比特反转噪声,并测量通过信道之后的量子比特。 \n",
......@@ -150,7 +150,7 @@
{
"cell_type": "code",
"execution_count": 2,
"id": "dafbad73",
"id": "70674a65",
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-08T05:16:09.221527Z",
......@@ -199,7 +199,7 @@
},
{
"cell_type": "markdown",
"id": "ec2b613e",
"id": "0c42a154",
"metadata": {},
"source": [
"可以看到,经过了比特反转信道(概率为 $p=0.1$)之后的量子态变成了混合态 $0.9 | 0 \\rangle \\langle 0 | + 0.1 | 1 \\rangle \\langle 1 |$。\n",
......@@ -208,7 +208,7 @@
},
{
"cell_type": "markdown",
"id": "fda5577a",
"id": "3725bece",
"metadata": {},
"source": [
"### 常用噪声信道\n",
......@@ -216,7 +216,7 @@
"除了比特反转信道之外,Paddle Quantum 也支持模拟其他常用的噪声信道。\n",
"\n",
"\n",
"- **相位反转信道(Phase Flip Channel)**\n",
"- **相位反转信道(phase flip channel)**\n",
"\n",
" 与比特反转信道类似,相位反转信道会以 $p$ 的概率来反转一个量子比特的相位,其表达形式为\n",
" \n",
......@@ -226,7 +226,7 @@
" $$\n",
"\n",
"\n",
"- **比特相位反转信道(Bit-Phase Flip Channel)**\n",
"- **比特相位反转信道(bit-phase flip channel)**\n",
"\n",
" $$\n",
" \\mathcal{E}_{BPF}(\\rho) = (1-p) \\rho + p Y \\rho Y.\n",
......@@ -234,7 +234,7 @@
" $$\n",
"\n",
"\n",
"- **去极化信道 (Depolarizing Channel)**\n",
"- **去极化信道 (depolarizing channel)**\n",
"\n",
" 通过去极化信道之后,将会有 $p$ 的概率处于最大混态 $I/2$ 和 $1-p$ 的概率维持不变。可以表示为对称地施加泡利噪声,\n",
" \n",
......@@ -245,7 +245,7 @@
" $$\n",
"\n",
"\n",
"- **泡利信道(Pauli Channel)**\n",
"- **泡利信道(Pauli channel)**\n",
"\n",
" 该信道会以非对称的形式施加泡利噪声。表达形式为\n",
" \n",
......@@ -255,7 +255,7 @@
" $$\n",
"\n",
"\n",
"- **振幅阻尼信道(Amplitude Damping Channel)**\n",
"- **振幅阻尼信道(amplitude damping channel)**\n",
"\n",
" 振幅阻尼信道可以用来模拟当系统受到**能量耗散**时引入的噪声。表达形式为,\n",
" \n",
......@@ -279,7 +279,7 @@
" $$ \n",
"\n",
"\n",
"- **相位阻尼信道(Phase Damping Channel)**\n",
"- **相位阻尼信道(phase damping channel)**\n",
"\n",
" 相位阻尼信道描述的是当系统没有与外界环境交换能量,却损失了**量子信息**的情况下的噪声模型。其表达形式为\n",
" \n",
......@@ -303,7 +303,7 @@
" $$\n",
"\n",
"\n",
"- **广义振幅阻尼信道(Generalized Amplitude Damping Channel)**\n",
"- **广义振幅阻尼信道(generalized amplitude Damping channel)**\n",
"\n",
" 该信道描述的是系统与外界环境在**有限温度下交换能量**的噪声模型,同时也是**超导量子计算中的常见噪声** [4]。其表达形式较为复杂,感兴趣的读者可以进一步的阅读 [API 文档](https://qml.baidu.com/api/paddle_quantum.circuit.uansatz.html) 和相应的参考文献。\n",
"\n",
......@@ -315,7 +315,7 @@
},
{
"cell_type": "markdown",
"id": "9c831b79",
"id": "213994a9",
"metadata": {},
"source": [
"### 自定义信道\n",
......@@ -326,7 +326,7 @@
{
"cell_type": "code",
"execution_count": 3,
"id": "a6596c31",
"id": "020ab93f",
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-08T05:17:30.681411Z",
......@@ -385,7 +385,7 @@
},
{
"cell_type": "markdown",
"id": "e9577b5e",
"id": "df1c24d9",
"metadata": {},
"source": [
"按照上述例子,用户可以通过自定义 *Kraus* 算符的方式实现特定的信道。"
......@@ -393,19 +393,19 @@
},
{
"cell_type": "markdown",
"id": "b8adc0fc",
"id": "e97e1bcd",
"metadata": {},
"source": [
"## 拓展:Paddle Quantum 模拟含噪纠缠资源\n",
"\n",
"\n",
"许多重要的量子技术,例如量子隐形传态、态转换、分布式量子计算等都需要纠缠资源的预先分配。以纠缠量子比特对为例,在理想情况下,我们希望分配的纠缠资源处于**最大纠缠态**(Maximally entangled state)。但是在实际的应用中,纠缠资源往往在制备、传输以及保存的过程中会和环境发生相互作用,从而引入噪声。下面,我们用 Paddle Quantum 中的去极化信道来模拟一个简单的场景,白噪声对贝尔态的影响:"
"许多重要的量子技术,例如量子隐形传态、态转换、分布式量子计算等都需要纠缠资源的预先分配。以纠缠量子比特对为例,在理想情况下,我们希望分配的纠缠资源处于**最大纠缠态**(maximally entangled state)。但是在实际的应用中,纠缠资源往往在制备、传输以及保存的过程中会和环境发生相互作用,从而引入噪声。下面,我们用 Paddle Quantum 中的去极化信道来模拟一个简单的场景,白噪声对贝尔态的影响:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "840210e5",
"id": "2a73505a",
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-08T05:24:35.552425Z",
......@@ -463,21 +463,21 @@
},
{
"cell_type": "markdown",
"id": "d6f209be",
"id": "85c5fcc6",
"metadata": {},
"source": [
"**注释:** 在 [纠缠蒸馏](https://qml.baidu.com/tutorials/loccnet/entanglement-distillation-with-loccnet.html) 的教程中我们介绍了如何利用 Paddle Quantm 中的 LoccNet 模块来研究纠缠蒸馏,即利用多个含噪声的纠缠对来提取高保真度的纠缠对,感兴趣的读者可以前往阅读。"
"**注释:** 在 [纠缠蒸馏](../locc/EntanglementDistillation_LOCCNET_CN.ipynb) 的教程中我们介绍了如何利用 Paddle Quantm 中的 LoccNet 模块来研究纠缠蒸馏,即利用多个含噪声的纠缠对来提取高保真度的纠缠对,感兴趣的读者可以前往阅读。"
]
},
{
"cell_type": "markdown",
"id": "ba1b1b03",
"id": "2e42f021",
"metadata": {},
"source": [
"## 应用: Paddle Quantum 模拟含噪变分量子本征求解器(VQE)\n",
"\n",
"\n",
"变分量子本征求解器(Variational Quantum Eigensolver)[5] 可以用变分量子电路来计算某个给定哈密顿量的基态能量,关于其具体的原理和背景在之前的教程 [变分量子本征求解器](https://qml.baidu.com/tutorials/variational-quantum-eigensolver.html) 中有详细的讲解,感兴趣的读者可以前往阅读。\n",
"变分量子本征求解器(variational quantum eigensolver, VQE)[5] 可以用变分量子电路来计算某个给定哈密顿量的基态能量,关于其具体的原理和背景在之前的教程 [变分量子本征求解器](../quantum_simulation/VQE_CN.ipynb) 中有详细的讲解,感兴趣的读者可以前往阅读。\n",
"\n",
"在这里,我们尝试用一个简单的 VQE 电路来求解如下哈密顿量的基态能量:\n",
"\n",
......@@ -492,7 +492,7 @@
{
"cell_type": "code",
"execution_count": 5,
"id": "15667852",
"id": "ab0fff8f",
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-08T05:34:47.301281Z",
......@@ -524,7 +524,7 @@
{
"cell_type": "code",
"execution_count": 6,
"id": "067b17a6",
"id": "b498f6c6",
"metadata": {
"ExecuteTime": {
"end_time": "2021-04-08T05:34:51.742273Z",
......@@ -683,7 +683,7 @@
},
{
"cell_type": "markdown",
"id": "f8310983",
"id": "48e09aa7",
"metadata": {},
"source": [
"可以看到,含噪的变分量子本征求解器的效果要差于不含噪的版本,无法达到化学精度的要求 $\\varepsilon = 0.0016$ Ha。"
......@@ -691,7 +691,7 @@
},
{
"cell_type": "markdown",
"id": "12608b8d",
"id": "8e0b51c6",
"metadata": {},
"source": [
"## 总结\n",
......@@ -701,7 +701,7 @@
},
{
"cell_type": "markdown",
"id": "8599bc86",
"id": "ea92b769",
"metadata": {},
"source": [
"---\n",
......@@ -736,7 +736,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
......
......@@ -441,7 +441,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Note:** Interested readers can check tutorials on the LOCCNet module of Paddle Quantum, where we discuss the concept of [entanglement distillation](https://qml.baidu.com/tutorials/loccnet/entanglement-distillation-with-loccnet.html)."
"**Note:** Interested readers can check tutorials on the LOCCNet module of Paddle Quantum, where we discuss the concept of [entanglement distillation](../locc/EntanglementDistillation_LOCCNET_EN.ipynb)."
]
},
{
......@@ -451,7 +451,7 @@
"## Application: Simulating noisy VQE with Paddle Quantum\n",
"\n",
"\n",
"Variational Quantum Eigensolver (VQE) [5] is designed to find the ground state energy of a given molecular Hamiltonian using variational quantum circuits. Interested readers can find more details from the previous tutorial [VQE](https://qml.baidu.com/tutorials/variational-quantum-eigensolver.html).\n",
"Variational Quantum Eigensolver (VQE) [5] is designed to find the ground state energy of a given molecular Hamiltonian using variational quantum circuits. Interested readers can find more details from the previous tutorial [VQE](../quantum_simulation/VQE_EN.ipynb).\n",
"\n",
"For illustration purposes, we use VQE to find the ground state energy for the following Hamiltonian: \n",
"\n",
......@@ -705,7 +705,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......
......@@ -74,8 +74,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:50.083834Z",
"start_time": "2021-01-09T10:26:46.286098Z"
"end_time": "2021-04-30T08:55:59.838299Z",
"start_time": "2021-04-30T08:55:57.450922Z"
}
},
"outputs": [],
......@@ -121,8 +121,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:50.115012Z",
"start_time": "2021-01-09T10:26:50.087603Z"
"end_time": "2021-04-30T08:55:59.855633Z",
"start_time": "2021-04-30T08:55:59.841241Z"
}
},
"outputs": [],
......@@ -138,8 +138,8 @@
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:50.142645Z",
"start_time": "2021-01-09T10:26:50.122554Z"
"end_time": "2021-04-30T08:55:59.935612Z",
"start_time": "2021-04-30T08:55:59.866942Z"
}
},
"outputs": [],
......@@ -186,8 +186,8 @@
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:50.162257Z",
"start_time": "2021-01-09T10:26:50.152881Z"
"end_time": "2021-04-30T08:56:01.029894Z",
"start_time": "2021-04-30T08:56:01.022404Z"
}
},
"outputs": [],
......@@ -210,7 +210,7 @@
" # 量子神经网络作用在给定的初始态上\n",
" final_state = cir.run_density_matrix(initial_state)\n",
"\n",
" return final_state"
" return final_state, cir"
]
},
{
......@@ -243,8 +243,8 @@
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:58.251869Z",
"start_time": "2021-01-09T10:26:58.241912Z"
"end_time": "2021-04-30T08:56:03.701245Z",
"start_time": "2021-04-30T08:56:03.691389Z"
}
},
"outputs": [],
......@@ -265,7 +265,7 @@
" def forward(self, H, N, N_SYS_B, D):\n",
"\n",
" # 施加量子神经网络\n",
" rho_AB = U_theta(self.initial_state, self.theta, N, D)\n",
" rho_AB, cir = U_theta(self.initial_state, self.theta, N, D)\n",
"\n",
" # 计算偏迹 partial trace 来获得子系统B所处的量子态 rho_B\n",
" rho_B = partial_trace(rho_AB, 2 ** (N - N_SYS_B), 2 ** (N_SYS_B), 1)\n",
......@@ -279,7 +279,7 @@
" # 最终的损失函数\n",
" loss = loss1 + loss2 + loss3 \n",
"\n",
" return loss, rho_B"
" return loss, rho_B, cir"
]
},
{
......@@ -301,8 +301,8 @@
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:59.447344Z",
"start_time": "2021-01-09T10:26:59.431177Z"
"end_time": "2021-04-30T08:56:05.260360Z",
"start_time": "2021-04-30T08:56:05.251628Z"
}
},
"outputs": [],
......@@ -324,7 +324,7 @@
"metadata": {},
"source": [
"- 当训练模型的各项参数都设置完成后,我们将数据转化为 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/paddle/optimizer/adam/Adam_cn.html),也可以调用 Paddle 中提供的其他优化器。\n",
"- 我们将训练过程中的结果依次输出。\n",
"- 特别地,我们依次输出了我们学习到的量子态 $\\rho_B(\\theta)$ 与吉布斯态 $\\rho_G$ 的保真度,保真度越高说明QNN输出的态越接近于吉布斯态。"
]
......@@ -334,8 +334,8 @@
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:27:03.596048Z",
"start_time": "2021-01-09T10:27:00.320786Z"
"end_time": "2021-04-30T08:56:19.753228Z",
"start_time": "2021-04-30T08:56:15.379159Z"
}
},
"outputs": [
......@@ -347,7 +347,17 @@
"iter: 20 loss: -3.3375 fid: 0.9799\n",
"iter: 30 loss: -3.3692 fid: 0.9897\n",
"iter: 40 loss: -3.3990 fid: 0.9929\n",
"iter: 50 loss: -3.4133 fid: 0.9959\n"
"iter: 50 loss: -3.4133 fid: 0.9959\n",
"\n",
"训练后的电路:\n",
"--Ry(6.262)----*--------------X----Ry(0.747)--\n",
" | | \n",
"--Ry(4.710)----X----*---------|----Ry(6.253)--\n",
" | | \n",
"--Ry(-0.01)---------X----*----|----Ry(-0.03)--\n",
" | | \n",
"--Ry(-0.00)--------------X----*----Ry(6.312)--\n",
" \n"
]
}
],
......@@ -368,7 +378,7 @@
"for itr in range(1, ITR + 1):\n",
" \n",
" # 前向传播计算损失函数并返回生成的量子态 rho_B\n",
" loss, rho_B = net(H, N, N_SYS_B, D)\n",
" loss, rho_B, cir = net(H, N, N_SYS_B, D)\n",
" \n",
" # 反向传播极小化损失函数\n",
" loss.backward()\n",
......@@ -381,7 +391,10 @@
" \n",
" # 打印训练结果\n",
" if itr % 10 == 0:\n",
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:', '%.4f' % fid)"
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:', '%.4f' % fid)\n",
" if itr == ITR:\n",
" print(\"\\n训练后的电路:\")\n",
" print(cir)"
]
},
{
......@@ -437,7 +450,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......
......@@ -25,7 +25,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"This tutorial will show how to train a quantum neural network (QNN) through Paddle Quantum to prepare a quantum Gibbs state.\n"
"This tutorial will show how to train a quantum neural network (QNN) through Paddle Quantum to prepare a quantum Gibbs state."
]
},
{
......@@ -71,8 +71,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:18.115601Z",
"start_time": "2021-01-09T10:26:14.563581Z"
"end_time": "2021-04-30T08:56:40.078886Z",
"start_time": "2021-04-30T08:56:36.868403Z"
}
},
"outputs": [],
......@@ -118,8 +118,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:18.156435Z",
"start_time": "2021-01-09T10:26:18.118621Z"
"end_time": "2021-04-30T08:56:40.099967Z",
"start_time": "2021-04-30T08:56:40.082138Z"
}
},
"outputs": [],
......@@ -135,8 +135,8 @@
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:18.185219Z",
"start_time": "2021-01-09T10:26:18.161336Z"
"end_time": "2021-04-30T08:56:40.201757Z",
"start_time": "2021-04-30T08:56:40.106315Z"
}
},
"outputs": [],
......@@ -182,8 +182,8 @@
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:18.202627Z",
"start_time": "2021-01-09T10:26:18.188216Z"
"end_time": "2021-04-30T08:56:40.213503Z",
"start_time": "2021-04-30T08:56:40.205311Z"
}
},
"outputs": [],
......@@ -206,7 +206,7 @@
" # The QNN acts on a given initial state\n",
" final_state = cir.run_density_matrix(initial_state)\n",
"\n",
" return final_state"
" return final_state, cir"
]
},
{
......@@ -239,8 +239,8 @@
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:18.589450Z",
"start_time": "2021-01-09T10:26:18.574464Z"
"end_time": "2021-04-30T08:56:40.238960Z",
"start_time": "2021-04-30T08:56:40.228348Z"
}
},
"outputs": [],
......@@ -261,7 +261,7 @@
" def forward(self, H, N, N_SYS_B, D):\n",
"\n",
" # Apply QNN\n",
" rho_AB = U_theta(self.initial_state, self.theta, N, D)\n",
" rho_AB, cir = U_theta(self.initial_state, self.theta, N, D)\n",
"\n",
" # Calculate partial trace to obtain the quantum state rho_B of subsystem B\n",
" rho_B = partial_trace(rho_AB, 2 ** (N-N_SYS_B), 2 ** (N_SYS_B), 1)\n",
......@@ -275,7 +275,7 @@
" # Final loss function\n",
" loss = loss1 + loss2 + loss3\n",
"\n",
" return loss, rho_B"
" return loss, rho_B, cir"
]
},
{
......@@ -297,8 +297,8 @@
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:20.193223Z",
"start_time": "2021-01-09T10:26:20.180849Z"
"end_time": "2021-04-30T08:56:40.966455Z",
"start_time": "2021-04-30T08:56:40.959537Z"
}
},
"outputs": [],
......@@ -320,7 +320,7 @@
"metadata": {},
"source": [
"- 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/paddle/optimizer/adam/Adam_en.html). Other optimizers are also provided in PaddlePaddle.\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."
]
......@@ -330,8 +330,8 @@
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-01-09T10:26:24.585128Z",
"start_time": "2021-01-09T10:26:21.249352Z"
"end_time": "2021-04-30T08:56:50.509486Z",
"start_time": "2021-04-30T08:56:47.508586Z"
}
},
"outputs": [
......@@ -343,7 +343,17 @@
"iter: 20 loss: -3.3375 fid: 0.9799\n",
"iter: 30 loss: -3.3692 fid: 0.9897\n",
"iter: 40 loss: -3.3990 fid: 0.9929\n",
"iter: 50 loss: -3.4133 fid: 0.9959\n"
"iter: 50 loss: -3.4133 fid: 0.9959\n",
"\n",
"The trained circuit:\n",
"--Ry(6.262)----*--------------X----Ry(0.747)--\n",
" | | \n",
"--Ry(4.710)----X----*---------|----Ry(6.253)--\n",
" | | \n",
"--Ry(-0.01)---------X----*----|----Ry(-0.03)--\n",
" | | \n",
"--Ry(-0.00)--------------X----*----Ry(6.312)--\n",
" \n"
]
}
],
......@@ -364,7 +374,7 @@
"for itr in range(1, ITR + 1):\n",
" \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, cir = net(H, N, N_SYS_B, D)\n",
" \n",
" # Run back propagation to minimize the loss function\n",
" loss.backward()\n",
......@@ -377,36 +387,24 @@
" \n",
" # Print training results\n",
" if itr% 10 == 0:\n",
" print('iter:', itr,'loss:','%.4f'% loss.numpy(),'fid:','%.4f'% fid)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusion"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"According to the results obtained from the above training, after about 50 iterations, we can achieve a high-precision Gibbs state with a fidelity higher than 99.5% and complete the preparation of the Gibbs state efficiently and accurately. We can output the QNN's learned parameters and its output state through the print function."
" print('iter:', itr,'loss:','%.4f'% loss.numpy(),'fid:','%.4f'% fid)\n",
" if itr == ITR:\n",
" print(\"\\nThe trained circuit:\")\n",
" print(cir)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"According to the results obtained from the above training, after about 50 iterations, we can achieve a high-precision Gibbs state with a fidelity higher than 99.5% and complete the preparation of the Gibbs state efficiently and accurately. We can output the QNN's learned parameters and its output state through the print function.\n",
"\n",
"_______\n",
"\n",
"## References"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## References\n",
"\n",
"[1] Kieferová, M. & Wiebe, N. Tomography and generative training with quantum Boltzmann machines. [Phys. Rev. A 96, 062327 (2017).](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.96.062327)\n",
"\n",
"[2] Brandao, F. G. S. L. & Svore, K. M. Quantum Speed-Ups for Solving Semidefinite Programs. [in 2017 IEEE 58th Annual Symposium on Foundations of Computer Science (FOCS) 415–426 (IEEE, 2017). ](https://ieeexplore.ieee.org/abstract/document/8104077)\n",
......@@ -433,7 +431,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......@@ -446,7 +444,7 @@
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
"toc_window_display": false
}
},
"nbformat": 4,
......
......@@ -20,8 +20,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:40:57.525085Z",
"start_time": "2021-03-09T03:40:54.923948Z"
"end_time": "2021-04-30T09:12:57.571029Z",
"start_time": "2021-04-30T09:12:54.960356Z"
}
},
"outputs": [],
......@@ -41,8 +41,8 @@
"## 背景\n",
"\n",
"- 量子计算在近期内备受瞩目的一个应用就是变分量子本征求解器(variational quantum eigensolver, VQE)[1-3].\n",
"- VQE 是量子化学在近期有噪量子设备(NISQ device)上的核心应用之一,其中一个功能比较强大的版本是 subspace-search VQE(SSVQE) [4],其核心是去求解一个物理系统的 Hamilton 量(Hamiltonian)的基态和**激发态**的性质。数学上,可以理解为求解一个 Hermite 矩阵(Hermitian matrix)的本征值及其对应的本征向量。该 Hamilton 量的本征值组成的集合我们称其为能谱(energy spectrum)。\n",
"- 接下来我们将通过一个简单的例子学习如何通过训练量子神经网络解决这个问题,即求解出给定 Hamilton 量 $H$ 的能谱。\n",
"- VQE 是量子化学在近期有噪量子设备(NISQ device)上的核心应用之一,其中一个功能比较强大的版本是 subspace-search VQE(SSVQE) [4],其核心是去求解一个物理系统的哈密顿量(Hamiltonian)的基态和**激发态**的性质。数学上,可以理解为求解一个埃尔米特矩阵矩阵(Hermitian matrix)的本征值及其对应的本征向量。该哈密顿量的本征值组成的集合我们称其为能谱(energy spectrum)。\n",
"- 接下来我们将通过一个简单的例子学习如何通过训练量子神经网络解决这个问题,即求解出给定哈密顿量 $H$ 的能谱。\n",
"\n",
"## SSVQE 分析物理系统的基态和激发态的能量\n",
"\n",
......@@ -55,8 +55,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:40:57.538850Z",
"start_time": "2021-03-09T03:40:57.527973Z"
"end_time": "2021-04-30T09:12:57.580461Z",
"start_time": "2021-04-30T09:12:57.574080Z"
}
},
"outputs": [],
......@@ -70,8 +70,8 @@
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:40:57.556193Z",
"start_time": "2021-03-09T03:40:57.544832Z"
"end_time": "2021-04-30T09:12:57.604652Z",
"start_time": "2021-04-30T09:12:57.592553Z"
}
},
"outputs": [
......@@ -85,7 +85,7 @@
}
],
"source": [
"# 生成用泡利字符串表示的随机 Hamilton 量\n",
"# 生成用泡利字符串表示的随机哈密顿量\n",
"numpy.random.seed(SEED)\n",
"hamiltonian = random_pauli_str_generator(N, terms=10)\n",
"print(\"Random Hamiltonian in Pauli string format = \\n\", hamiltonian)\n",
......@@ -110,8 +110,8 @@
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:40:57.570458Z",
"start_time": "2021-03-09T03:40:57.559295Z"
"end_time": "2021-04-30T09:12:57.673600Z",
"start_time": "2021-04-30T09:12:57.664882Z"
}
},
"outputs": [],
......@@ -128,8 +128,8 @@
" # 调用内置的量子神经网络模板\n",
" cir.universal_2_qubit_gate(theta, [0, 1])\n",
"\n",
" # 返回量子神经网络所模拟的酉矩阵 U\n",
" return cir.U"
" # 返回量子神经网络的电路\n",
" return cir"
]
},
{
......@@ -142,7 +142,7 @@
"\n",
"- 通过作用量子神经网络 $U(\\theta)$ 在一组正交的初始态上(方便起见,可以取计算基 $\\{|00\\rangle, |01\\rangle, |10\\rangle, |11\\rangle \\}$),我们将得到输出态 $\\{\\left| {\\psi_1 \\left( {\\bf{\\theta }} \\right)} \\right\\rangle, \\left| {\\psi_2 \\left( {\\bf{\\theta }} \\right)} \\right\\rangle, \\left| {\\psi_3 \\left( {\\bf{\\theta }} \\right)} \\right\\rangle, \\left| {\\psi_4 \\left( {\\bf{\\theta }} \\right)} \\right\\rangle \\}$。\n",
"\n",
"- 进一步,在 SSVQE 模型中的损失函数一般由每个输出量子态 $\\left| {\\psi_k \\left( {\\bf{\\theta }} \\right)} \\right\\rangle$ 关于 Hamilton 量 $H$ 的能量期望值(expectation value)的加权求和给出。这里我们默认权重向量 $\\vec{w} = [4, 3, 2, 1]$。\n",
"- 进一步,在 SSVQE 模型中的损失函数一般由每个输出量子态 $\\left| {\\psi_k \\left( {\\bf{\\theta }} \\right)} \\right\\rangle$ 关于哈密顿量 $H$ 的能量期望值(expectation value)的加权求和给出。这里我们默认权重向量 $\\vec{w} = [4, 3, 2, 1]$。\n",
"\n",
"- 具体的损失函数(loss function)定义为:\n",
"\n",
......@@ -156,8 +156,8 @@
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:40:58.810111Z",
"start_time": "2021-03-09T03:40:58.794879Z"
"end_time": "2021-04-30T09:12:58.591349Z",
"start_time": "2021-04-30T09:12:58.577120Z"
}
},
"outputs": [],
......@@ -175,7 +175,8 @@
" def forward(self, H, N):\n",
" \n",
" # 构造量子神经网络\n",
" U = U_theta(self.theta, N)\n",
" cir = U_theta(self.theta, N)\n",
" U = cir.U\n",
" \n",
" # 计算损失函数\n",
" loss_struct = paddle.real(matmul(matmul(dagger(U), H), U))\n",
......@@ -192,7 +193,7 @@
" loss = 4 * loss_components[0] + 3 * loss_components[1]\\\n",
" + 2 * loss_components[2] + 1 * loss_components[3]\n",
" \n",
" return loss, loss_components"
" return loss, loss_components, cir"
]
},
{
......@@ -208,8 +209,8 @@
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:00.676449Z",
"start_time": "2021-03-09T03:41:00.667746Z"
"end_time": "2021-04-30T09:12:59.351881Z",
"start_time": "2021-04-30T09:12:59.343240Z"
}
},
"outputs": [],
......@@ -233,8 +234,8 @@
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:11.696116Z",
"start_time": "2021-03-09T03:41:08.683371Z"
"end_time": "2021-04-30T09:13:07.503094Z",
"start_time": "2021-04-30T09:13:04.968574Z"
}
},
"outputs": [
......@@ -251,7 +252,13 @@
"iter: 70 loss: -5.9739\n",
"iter: 80 loss: -5.9833\n",
"iter: 90 loss: -5.9846\n",
"iter: 100 loss: -5.9848\n"
"iter: 100 loss: -5.9848\n",
"\n",
"训练后的电路:\n",
"--U----X----Rz(-1.18)----*-----------------X----U--\n",
" | | | \n",
"--U----*----Ry(-0.03)----X----Ry(2.362)----*----U--\n",
" \n"
]
}
],
......@@ -272,7 +279,7 @@
"for itr in range(1, ITR + 1):\n",
"\n",
" # 前向传播计算损失函数并返回估计的能谱\n",
" loss, loss_components = net(hamiltonian, N)\n",
" loss, loss_components, cir = net(hamiltonian, N)\n",
"\n",
" # 在动态图机制下,反向传播极小化损失函数\n",
" loss.backward()\n",
......@@ -281,7 +288,10 @@
"\n",
" # 打印训练结果\n",
" if itr % 10 == 0:\n",
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])"
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])\n",
" if itr == ITR:\n",
" print(\"\\n训练后的电路:\")\n",
" print(cir)"
]
},
{
......@@ -291,7 +301,7 @@
"## 测试效果\n",
"\n",
"我们现在已经完成了量子神经网络的训练,我们将通过与理论值的对比来测试效果。\n",
"- 理论值由 NumPy 中的工具来求解 Hamilton 量的各个本征值;\n",
"- 理论值由 NumPy 中的工具来求解哈密顿量的各个本征值;\n",
"- 我们将训练 QNN 得到的各个能级的能量和理想情况下的理论值进行比对。\n",
"- 可以看到,SSVQE 训练输出的值与理想值高度接近。"
]
......@@ -301,8 +311,8 @@
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:14.595062Z",
"start_time": "2021-03-09T03:41:14.562037Z"
"end_time": "2021-04-30T09:13:07.569109Z",
"start_time": "2021-04-30T09:13:07.522441Z"
}
},
"outputs": [
......@@ -372,7 +382,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......
......@@ -20,8 +20,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:35.275034Z",
"start_time": "2021-03-09T03:41:30.979161Z"
"end_time": "2021-04-30T09:12:27.747028Z",
"start_time": "2021-04-30T09:12:25.171248Z"
}
},
"outputs": [],
......@@ -54,8 +54,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:35.325305Z",
"start_time": "2021-03-09T03:41:35.308814Z"
"end_time": "2021-04-30T09:12:27.773417Z",
"start_time": "2021-04-30T09:12:27.752568Z"
}
},
"outputs": [],
......@@ -69,8 +69,8 @@
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:35.352514Z",
"start_time": "2021-03-09T03:41:35.329030Z"
"end_time": "2021-04-30T09:12:27.804177Z",
"start_time": "2021-04-30T09:12:27.779339Z"
}
},
"outputs": [
......@@ -109,8 +109,8 @@
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:35.375932Z",
"start_time": "2021-03-09T03:41:35.358359Z"
"end_time": "2021-04-30T09:12:27.822250Z",
"start_time": "2021-04-30T09:12:27.809696Z"
}
},
"outputs": [],
......@@ -127,8 +127,8 @@
" # Call the built-in quantum neural network template\n",
" cir.universal_2_qubit_gate(theta, [0, 1])\n",
"\n",
" # Return the unitary matrix U simulated by the quantum neural network\n",
" return cir.U"
" # Return the circuit of the quantum neural network\n",
" return cir"
]
},
{
......@@ -155,8 +155,8 @@
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:35.410903Z",
"start_time": "2021-03-09T03:41:35.382213Z"
"end_time": "2021-04-30T09:12:28.432737Z",
"start_time": "2021-04-30T09:12:28.423798Z"
}
},
"outputs": [],
......@@ -174,7 +174,8 @@
" def forward(self, H, N):\n",
" \n",
" # Build quantum neural network\n",
" U = U_theta(self.theta, N)\n",
" cir = U_theta(self.theta, N)\n",
" U = cir.U\n",
" \n",
" # Calculate the loss function\n",
" loss_struct = paddle.real(matmul(matmul(dagger(U), H), U))\n",
......@@ -192,7 +193,7 @@
" loss = 4 * loss_components[0] + 3 * loss_components[1]\\\n",
" + 2 * loss_components[2] + 1 * loss_components[3]\n",
" \n",
" return loss, loss_components"
" return loss, loss_components, cir"
]
},
{
......@@ -209,8 +210,8 @@
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:35.422337Z",
"start_time": "2021-03-09T03:41:35.417772Z"
"end_time": "2021-04-30T09:12:29.579180Z",
"start_time": "2021-04-30T09:12:29.575632Z"
}
},
"outputs": [],
......@@ -234,8 +235,8 @@
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:43.095334Z",
"start_time": "2021-03-09T03:41:40.517746Z"
"end_time": "2021-04-30T09:12:44.010556Z",
"start_time": "2021-04-30T09:12:41.952650Z"
}
},
"outputs": [
......@@ -252,7 +253,13 @@
"iter: 70 loss: -5.9739\n",
"iter: 80 loss: -5.9833\n",
"iter: 90 loss: -5.9846\n",
"iter: 100 loss: -5.9848\n"
"iter: 100 loss: -5.9848\n",
"\n",
"The trained circuit:\n",
"--U----X----Rz(-1.18)----*-----------------X----U--\n",
" | | | \n",
"--U----*----Ry(-0.03)----X----Ry(2.362)----*----U--\n",
" \n"
]
}
],
......@@ -273,7 +280,7 @@
"for itr in range(1, ITR + 1):\n",
"\n",
" # Forward propagation calculates the loss function and returns the estimated energy spectrum\n",
" loss, loss_components = net(hamiltonian, N)\n",
" loss, loss_components, cir = net(hamiltonian, N)\n",
"\n",
" # Under the dynamic graph mechanism, use back propagation to minimize the loss function\n",
" loss.backward()\n",
......@@ -282,7 +289,10 @@
"\n",
" # Print training results\n",
" if itr% 10 == 0:\n",
" print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])"
" print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])\n",
" if itr == ITR:\n",
" print(\"\\nThe trained circuit:\")\n",
" print(cir)"
]
},
{
......@@ -302,8 +312,8 @@
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:41:43.152444Z",
"start_time": "2021-03-09T03:41:43.105409Z"
"end_time": "2021-04-30T09:12:45.991342Z",
"start_time": "2021-04-30T09:12:45.976287Z"
}
},
"outputs": [
......@@ -373,7 +383,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......
......@@ -94,7 +94,7 @@
"\\tag{7}\n",
"$$\n",
"\n",
"其中坐标 $|\\mathbf{x_j}\\rangle = |r_j\\rangle |\\sigma_j\\rangle$ 记录第 $j$ 个电子的空间位置信息和自旋,$|r_j\\rangle = |x_j,y_j,z_j\\rangle$ 且 $j\\in \\{1,2,\\cdots,N\\}$, $x_j,y_j,z_j \\in \\{0,1,\\cdots,k-1\\}$ 同时 $\\sigma_j \\in \\{\\downarrow,\\uparrow\\}$ 表示自旋向下和向上。这样一种离散化方式共计需要 $k^{3N}\\times 2^{N}$ 个数据来表示波函数。在这里,$\\mathcal{A}$ 表示反对称化操作(出于泡利不相容原理)并且 $\\psi(\\mathbf{x_1}, \\mathbf{x_2}, \\ldots, \\mathbf{x_N})=\\langle\\mathbf{x_1}, \\mathbf{x_2}, \\ldots, \\mathbf{x_N}|\\Psi\\rangle$。 可以看出,经典计算机存储这样一个波函数需要的内存是随着电子个数呈指数增长的。这使得基于这种离散化的经典数值方法,无法模拟超过几十个电子的系统。那么,我们是不是能够通过量子设备来存储和准备这样一个波函数然后求解基态能量 $E_0$ 呢?在下一节中,我们将以最简单的分子系统 -- 氢分子($H_2$)为例,讲解 VQE 算法。\n",
"其中坐标 $|\\mathbf{x_j}\\rangle = |r_j\\rangle |\\sigma_j\\rangle$ 记录第 $j$ 个电子的空间位置信息和自旋,$|r_j\\rangle = |x_j,y_j,z_j\\rangle$ 且 $j\\in \\{1,2,\\cdots,N\\}$, $x_j,y_j,z_j \\in \\{0,1,\\cdots,k-1\\}$ 同时 $\\sigma_j \\in \\{\\downarrow,\\uparrow\\}$ 表示自旋向下和向上。这样一种离散化方式共计需要 $k^{3N}\\times 2^{N}$ 个数据来表示波函数。在这里,$\\mathcal{A}$ 表示反对称化操作(出于泡利不相容原理)并且 $\\psi(\\mathbf{x_1}, \\mathbf{x_2}, \\ldots, \\mathbf{x_N})=\\langle\\mathbf{x_1}, \\mathbf{x_2}, \\ldots, \\mathbf{x_N}|\\Psi\\rangle$。 可以看出,经典计算机存储这样一个波函数需要的内存是随着电子个数呈指数增长的。这使得基于这种离散化的经典数值方法,无法模拟超过几十个电子的系统。那么,我们是不是能够通过量子设备来存储和准备这样一个波函数然后求解基态能量 $E_0$ 呢?在下一节中,我们将以最简单的分子系统 -- 氢分子($H_2$)为例,讲解 VQE 算法。\n",
"\n",
"**注释2:** 关于量子化学和现有数值计算方法的综述也超过了本教程的处理范围,我们推荐感兴趣的读者去查阅以下经典教材 Helgaker 等人撰写的 *'Molecular Electronic-Structure Theory'* [6] 以及 Szabo & Ostlund 撰写的 *'Modern Quantum Chemistry: Introduction to Advanced Electronic Structure Theory'* [8]。 如果需要弥补量子计算和量子化学之间知识空缺,请参考以下综述文章 [Quantum chemistry in the age of quantum computing](https://pubs.acs.org/doi/10.1021/acs.chemrev.8b00803) [1] 和 [Quantum computational chemistry](https://journals.aps.org/rmp/abstract/10.1103/RevModPhys.92.015003) [2] 。\n",
"\n",
......@@ -115,11 +115,11 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:38:25.880887Z",
"start_time": "2021-03-09T03:38:23.112486Z"
"end_time": "2021-04-30T09:13:45.528201Z",
"start_time": "2021-04-30T09:13:43.385553Z"
}
},
"outputs": [],
......@@ -149,11 +149,11 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:38:29.535703Z",
"start_time": "2021-03-09T03:38:29.530224Z"
"end_time": "2021-04-30T09:13:45.545018Z",
"start_time": "2021-04-30T09:13:45.531302Z"
}
},
"outputs": [],
......@@ -173,8 +173,8 @@
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:36:14.021622Z",
"start_time": "2021-03-09T03:35:52.518925Z"
"end_time": "2021-04-30T09:13:49.924911Z",
"start_time": "2021-04-30T09:13:45.604181Z"
}
},
"outputs": [],
......@@ -188,8 +188,8 @@
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:36:21.227368Z",
"start_time": "2021-03-09T03:36:14.028819Z"
"end_time": "2021-04-30T09:13:57.494843Z",
"start_time": "2021-04-30T09:13:55.235443Z"
}
},
"outputs": [],
......@@ -203,8 +203,8 @@
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:38:50.158332Z",
"start_time": "2021-03-09T03:38:47.301344Z"
"end_time": "2021-04-30T09:14:00.836635Z",
"start_time": "2021-04-30T09:13:58.092862Z"
}
},
"outputs": [
......@@ -270,8 +270,8 @@
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:38:51.614460Z",
"start_time": "2021-03-09T03:38:51.605394Z"
"end_time": "2021-04-30T09:14:00.852699Z",
"start_time": "2021-04-30T09:14:00.842277Z"
}
},
"outputs": [],
......@@ -326,8 +326,8 @@
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:38:52.753996Z",
"start_time": "2021-03-09T03:38:52.746918Z"
"end_time": "2021-04-30T09:14:01.746172Z",
"start_time": "2021-04-30T09:14:01.738712Z"
}
},
"outputs": [],
......@@ -353,7 +353,7 @@
" # 计算给定哈密顿量的期望值\n",
" expectation_val = cir.expecval(Hamiltonian)\n",
"\n",
" return expectation_val"
" return expectation_val, cir"
]
},
{
......@@ -376,8 +376,8 @@
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:38:53.511563Z",
"start_time": "2021-03-09T03:38:53.505570Z"
"end_time": "2021-04-30T09:14:02.737957Z",
"start_time": "2021-04-30T09:14:02.728041Z"
}
},
"outputs": [],
......@@ -399,9 +399,9 @@
" def forward(self, N, D):\n",
" \n",
" # 计算损失函数/期望值\n",
" loss = U_theta(self.theta, Hamiltonian, N, D)\n",
" loss, cir = U_theta(self.theta, Hamiltonian, N, D)\n",
"\n",
" return loss"
" return loss, cir"
]
},
{
......@@ -418,8 +418,8 @@
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:38:54.477162Z",
"start_time": "2021-03-09T03:38:54.472259Z"
"end_time": "2021-04-30T09:14:03.744957Z",
"start_time": "2021-04-30T09:14:03.738881Z"
}
},
"outputs": [],
......@@ -440,11 +440,11 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 12,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:39:12.114397Z",
"start_time": "2021-03-09T03:38:55.265261Z"
"end_time": "2021-04-30T09:14:58.180112Z",
"start_time": "2021-04-30T09:14:31.954222Z"
}
},
"outputs": [
......@@ -452,14 +452,24 @@
"name": "stdout",
"output_type": "stream",
"text": [
"iter: 20 loss: -1.0791\n",
"iter: 20 Ground state energy: -1.0791 Ha\n",
"iter: 40 loss: -1.1288\n",
"iter: 40 Ground state energy: -1.1288 Ha\n",
"iter: 60 loss: -1.1353\n",
"iter: 60 Ground state energy: -1.1353 Ha\n",
"iter: 80 loss: -1.1361\n",
"iter: 80 Ground state energy: -1.1361 Ha\n"
"iter: 20 loss: -0.9930\n",
"iter: 20 Ground state energy: -0.9930 Ha\n",
"iter: 40 loss: -1.1221\n",
"iter: 40 Ground state energy: -1.1221 Ha\n",
"iter: 60 loss: -1.1333\n",
"iter: 60 Ground state energy: -1.1333 Ha\n",
"iter: 80 loss: -1.1359\n",
"iter: 80 Ground state energy: -1.1359 Ha\n",
"\n",
"训练后的电路:\n",
"--Ry(4.717)----*--------------X----Ry(4.718)----*--------------X----Ry(-0.02)--\n",
" | | | | \n",
"--Ry(4.733)----X----*---------|----Ry(4.486)----X----*---------|----Ry(4.828)--\n",
" | | | | \n",
"--Ry(-3.25)---------X----*----|----Ry(4.729)---------X----*----|----Ry(-0.01)--\n",
" | | | | \n",
"--Ry(-1.55)--------------X----*----Ry(4.704)--------------X----*----Ry(3.094)--\n",
" \n"
]
}
],
......@@ -478,7 +488,7 @@
"for itr in range(1, ITR + 1):\n",
"\n",
" # 前向传播计算损失函数\n",
" loss = net(N, D)\n",
" loss, cir = net(N, D)\n",
"\n",
" # 在动态图机制下,反向传播极小化损失函数\n",
" loss.backward()\n",
......@@ -494,6 +504,9 @@
" print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n",
" print(\"iter:\", itr, \"Ground state energy:\", \"%.4f Ha\" \n",
" % loss.numpy())\n",
" if itr == ITR:\n",
" print(\"\\n训练后的电路:\") \n",
" print(cir)\n",
"\n",
"# 储存训练结果到 output 文件夹\n",
"os.makedirs(\"output\", exist_ok=True)\n",
......@@ -514,14 +527,14 @@
"execution_count": 11,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:39:15.991207Z",
"start_time": "2021-03-09T03:39:14.982817Z"
"end_time": "2021-04-30T09:14:21.341323Z",
"start_time": "2021-04-30T09:14:20.710152Z"
}
},
"outputs": [
{
"data": {
"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",
"image/png": "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JqJZoihu48ZTDdmFGja0EoUxJqJZoiikCv/+96lqp0KWKIwxEc4SRaHsbDh48FRDdiFLFMYEbdeuXVx//fV06NCBlJQUBg4cyPTp06s1hszMTHr27Bn08QsXLuSbb76ptONqIksUhc45B/72N7jwwtP3x8dbG4UxQVBVRo0axaBBg9i8eTPp6elMmzaNrKysM44ta/a76hSOiaK63z9LFMU1bAj165++Lz4eDh2Ckye9icmYMPHFF18QExNTNDw3QLt27bj77rsBeOutt7jqqqsYMmQIQ4cOJTc3l1GjRtG7d2/OO+88MjIyAJg0aRJ//OMfi87Rs2dPMjMzyczMpFu3bkycOJEePXowYsQIjh49CriOdH369KFPnz68/PLLpcb45z//me7du9O7d2+uu+46MjMzeeWVV3j++edJSkpi8eLFzJo1iwEDBtC3b1+GDRvGrl27/B6XnZ3NNddcQ79+/ejXrx9ff/31GdcrKCjgwQcfpF+/fvTu3ZtXX30VcEnn4osvZsyYMUVjULlRNNzPctFFF5GSksIll1zCjh07ADet63333UdqaiovvPACS5cupXfv3iQlJfHggw8WlaIGDRrEihUrimK44IILWLlyZbl/n6cpbWyPcF3OeqynkmbNcuM97dtXuec1ppKVHL/nkUdU581z6ydOuO0vvnDbeXlue9Eit33okNv++mu3vX+/216yxG3n5pZ9/RdeeEHvu+++Up+fMmWKtm7dWnNyclRV9a677tJJkyapqur8+fO1T58+qqr6v//7v/rMM88Uva5Hjx66ZcsW3bJli0ZFReny5ctVVfXaa6/V//u//1NVN7bUl19+qaqqDzzwgPbo0cNvDC1bttS8vDxVVd27d6/f6+Xm5urJkydVVfX111/X+++/3+9x48aN08WLF6uq6tatW7Vr165nXO/VV1/Vxx9/XFVV8/LyNCUlRTdv3qwLFizQ+Ph43bZtmxYUFOh5552nixcv1uPHj+vAgQN19+7dqqo6bdo0vfnmm1XVjVt1xx13nPa+fPPNN6qq+vDDDxf9zG+99Zbee++9qqq6YcMG9fedWN6xnqxndlmKD+NRuG6MKdOdd97JV199RUxMTNGscMOHD6dJkyYAfPXVV/zjH/8AYMiQIeTk5HCgjGre9u3bF808l5KSQmZmJvv27WPfvn0MGjQIgJ///Od8+umn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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -618,7 +631,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.7.0"
},
"toc": {
"base_numbering": 1,
......@@ -631,7 +644,7 @@
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
"toc_window_display": false
}
},
"nbformat": 4,
......
......@@ -66,6 +66,7 @@
"$$\n",
"\n",
"The energy levels of the electrons in the molecule can be found by solving the time independent Schrödinger equation\n",
"\n",
"$$\n",
"\\hat{H}_{\\text{electron}} |\\Psi_n \\rangle = E_n |\\Psi_n \\rangle,\n",
"\\tag{6}\n",
......@@ -110,8 +111,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:39:38.503998Z",
"start_time": "2021-03-09T03:39:35.006563Z"
"end_time": "2021-04-30T09:14:44.970178Z",
"start_time": "2021-04-30T09:14:40.895128Z"
}
},
"outputs": [],
......@@ -144,8 +145,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:39:38.515263Z",
"start_time": "2021-03-09T03:39:38.507179Z"
"end_time": "2021-04-30T09:14:44.982005Z",
"start_time": "2021-04-30T09:14:44.975892Z"
}
},
"outputs": [],
......@@ -195,8 +196,8 @@
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:39:44.013859Z",
"start_time": "2021-03-09T03:39:40.605688Z"
"end_time": "2021-04-30T09:14:49.975774Z",
"start_time": "2021-04-30T09:14:45.126298Z"
}
},
"outputs": [
......@@ -263,8 +264,8 @@
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:39:44.035716Z",
"start_time": "2021-03-09T03:39:44.017820Z"
"end_time": "2021-04-30T09:14:50.043900Z",
"start_time": "2021-04-30T09:14:50.019574Z"
}
},
"outputs": [],
......@@ -318,8 +319,8 @@
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:39:44.048908Z",
"start_time": "2021-03-09T03:39:44.040479Z"
"end_time": "2021-04-30T09:14:50.083041Z",
"start_time": "2021-04-30T09:14:50.062255Z"
}
},
"outputs": [],
......@@ -345,7 +346,7 @@
" # Calculate the expected value of a given Hamiltonian\n",
" expectation_val = cir.expecval(Hamiltonian)\n",
"\n",
" return expectation_val"
" return expectation_val, cir"
]
},
{
......@@ -369,8 +370,8 @@
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:39:44.060734Z",
"start_time": "2021-03-09T03:39:44.052212Z"
"end_time": "2021-04-30T09:14:50.183996Z",
"start_time": "2021-04-30T09:14:50.167892Z"
}
},
"outputs": [],
......@@ -389,9 +390,9 @@
" def forward(self, N, D):\n",
" \n",
" # Calculate the loss function/expected value\n",
" loss = U_theta(self.theta, Hamiltonian, N, D)\n",
" loss, cir = U_theta(self.theta, Hamiltonian, N, D)\n",
"\n",
" return loss"
" return loss, cir"
]
},
{
......@@ -408,8 +409,8 @@
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:39:44.579037Z",
"start_time": "2021-03-09T03:39:44.575023Z"
"end_time": "2021-04-30T09:14:50.222465Z",
"start_time": "2021-04-30T09:14:50.187093Z"
}
},
"outputs": [],
......@@ -430,11 +431,11 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 10,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:40:22.805429Z",
"start_time": "2021-03-09T03:39:57.972353Z"
"end_time": "2021-04-30T09:15:52.165788Z",
"start_time": "2021-04-30T09:15:29.625076Z"
}
},
"outputs": [
......@@ -442,14 +443,24 @@
"name": "stdout",
"output_type": "stream",
"text": [
"iter: 20 loss: -1.0915\n",
"iter: 20 Ground state energy: -1.0915 Ha\n",
"iter: 40 loss: -1.1281\n",
"iter: 40 Ground state energy: -1.1281 Ha\n",
"iter: 60 loss: -1.1341\n",
"iter: 60 Ground state energy: -1.1341 Ha\n",
"iter: 20 loss: -1.0687\n",
"iter: 20 Ground state energy: -1.0687 Ha\n",
"iter: 40 loss: -1.1313\n",
"iter: 40 Ground state energy: -1.1313 Ha\n",
"iter: 60 loss: -1.1355\n",
"iter: 60 Ground state energy: -1.1355 Ha\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",
"\n",
"The trained circuit:\n",
"--Ry(1.557)----*--------------X----Ry(1.578)----*--------------X----Ry(3.142)--\n",
" | | | | \n",
"--Ry(1.571)----X----*---------|----Ry(4.916)----X----*---------|----Ry(1.390)--\n",
" | | | | \n",
"--Ry(2.972)---------X----*----|----Ry(7.847)---------X----*----|----Ry(3.104)--\n",
" | | | | \n",
"--Ry(4.663)--------------X----*----Ry(1.577)--------------X----*----Ry(3.147)--\n",
" \n"
]
}
],
......@@ -469,7 +480,7 @@
"for itr in range(1, ITR + 1):\n",
"\n",
" # Forward propagation to calculate loss function\n",
" loss = net(N, D)\n",
" loss, cir = net(N, D)\n",
"\n",
" # Use back propagation to minimize the loss function\n",
" loss.backward()\n",
......@@ -485,6 +496,9 @@
" print(\"iter:\", itr, \"loss:\", \"%.4f\" % loss.numpy())\n",
" print(\"iter:\", itr, \"Ground state energy:\", \"%.4f Ha\" \n",
" % loss.numpy())\n",
" if itr == ITR:\n",
" print(\"\\nThe trained circuit:\")\n",
" print(cir)\n",
"\n",
"# Save the training results to the output folder\n",
"os.makedirs(\"output\", exist_ok=True)\n",
......@@ -506,14 +520,14 @@
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:40:23.538082Z",
"start_time": "2021-03-09T03:40:22.810747Z"
"end_time": "2021-04-30T09:15:18.096944Z",
"start_time": "2021-04-30T09:15:17.481250Z"
}
},
"outputs": [
{
"data": {
"image/png": "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rlu3ToN9Jx7tWE82cVF5pZ3u9u6FKg4TYIw50nXXXcfHH39MQkJC2axwo0aNomXLlgB8/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+/YlIyOjwiutnn32Wa666ioyMjLYt28fzZo1K3ssMzOTlJQULr/88kpfu6qQil7UaJWVlaXZ2dnV38HWrfCLX8BNN8HIkbUXmDFhtmbNGnr27Ol3GKaOBLaH3HvvvWzevJmHHnoIgO+++45hw4axdu1aGjQ4sj4Q7LMiIjmqmnVEYaxGcSSrURhjosDbb79NRkYGvXv3ZsGCBdx1110ATJ06lZNOOok//elPQZNEdVhjdnmNGkFcnCUKY0xEGz9+fNlVUIEuvfTSWp9gyWoU5ZWOIGuJwkShWDuVbGpfdT4jliiCsWE8TBRKSkoiPz/fkoWpkKqSn58f8pLeYOzUUzA2MKCJQh06dCAvL49t27b5HYqJYElJSWUd/arKEkUwycmwfXvl5YyJIA0bNqywF7ExNWGnnoKxgQGNMaaMJYpgLFEYY0wZSxTBJCfDgQPgdbs3xpj6zBJFMKUjyFqtwhhjLFEEFTjUuDHG1HOWKIKxYTyMMaaMJYpgbKhxY4wpY4kiGKtRGGNMGV8ShYi0FJH3RWS9d3/EzBoikiEi/xWRVSKyXESOHP0qXKxGYYwxZfyqUUwC5qpqV2Cut17efuBSVe0FnA78XUSa10l0iYlu7khLFMYY41uiGAuUzjH4IjCufAFV/UJV13vL3wFbgdQ6ia50BFm76skYY3xLFG1VdbO3/D3QNlRhERkIJABfVfD41SKSLSLZtTYgmg0MaIwxQBgHBRSROcAxQR76TeCKqqqIVDgusoi0A/4JTFTVkmBlVPUp4ClwU6FWO+hANtS4McYAYUwUqlrhhNMiskVE2qnqZi8RbK2gXArwNvAbVf00TKEGl5wMW7bU6SGNMSYS+XXqaSYw0VueCLxRvoCIJAAzgKmqOr0OY3OsRmGMMYB/ieJeYJSIrAdGeuuISJaIPOOV+RkwBLhMRJZ5t4w6i9BGkDXGGMCniYtUNR8YEWR7NnClt/wv4F91HNqPkpPh4EEoLISEBN/CMMYYv1nP7IrYwIDGGANYoqhYaaKwS2SNMfWcJYqKlCaKqVNh/nxrrzDG1Fu+tFFEhW7dYMwY+PRTWLzY9dbOyIDbb/9x0EBjjKkHRLV2+qdFiqysLM3Ozq69HarC+vWwaBG89hqcdBJMmuQShzHGxAgRyVHVrGCPWY2iMiKudtGtm6tJPPccvPcenH6635EZY0ydsDaKozFuHPTrB08/Dd9843c0xhhTJyxRHA0R+NWvoFEjuP9+18fCGGNinCWKo9WihUsWubnuNJQxxsQ4SxTVkZkJo0fDO+/AoUN+R2OMMWFliaK6evSAkhLIz/c7EmOMCStLFNWV6k22V1sTJRljTISyRFFdpYlia9CpNIwxJmZYoqguSxTGmHrCEkV1JSRAs2Z26skYE/MsUdREmzZWozDGxDxLFDWRmmo1CmNMzLNEURNt2rhEEWMDKxpjTCBLFDXRpo0bxsMmNzLGxDBLFDVhVz4ZY+oBSxQ10aaNu7d2CmNMDAs5H4WIJAFnAYOBY4EfgJXA26q6KvzhRTjrnW2MqQcqTBQi8gdckpgPLAK2AklAN+BeL4ncoqrL6yDOyNS0KSQl2aknY0xMC1Wj+ExVf1/BY38TkTZAxzDEFD1EXK3CEoUxJoZV2Eahqm+HeqKqblXVak1OLSItReR9EVnv3bcIUTZFRPJE5NHqHCvsSi+RNcaYGFVpY7aIpIrIX0Vkloh8UHqr4XEnAXNVtSsw11uvyD3ARzU8XvhYjcIYE+OqctXTS8AaoBPwByAXWFzD444FXvSWXwTGBSskIplAW2B2DY8XPm3awJ49cOCA35EYY0xYVCVRtFLVZ4EiVf1QVa8AhtfwuG1VdbO3/D0uGRxGRBoADwC3VrYzEblaRLJFJHtbXZ8GsktkjTExLuTlsZ4i736ziJwJfAe0rOxJIjIHOCbIQ78JXFFVFZFgY2D8LzBLVfNEJOSxVPUp4CmArKysuh1PI7DT3XHH1emhjTGmLlQlUfxRRJoBtwCPACnAryp7kqqOrOgxEdkiIu1UdbOItMNdelveycBgEflfoCmQICJ7VTVUe0bdsxqFMSbGVZooVPUtb3EXcFotHXcmMBG417t/I8hxJ5Qui8hlQFbEJQmAFi2gQQNLFMaYmBWqw90jQIWncVT1xhoc917gVRH5BfA18DPvmFnANap6ZQ32Xbfi4qB1a0sUxpiYFapGEdhH4g9ARZ3vjpqq5gMjgmzPBo5IEqr6AvBCbR2/1tkERsaYGFZholDV0stXEZGbA9dNOampsHKl31EYY0xYVHX0WJuZJ5TUVMjPh+JivyMxxphaZ8OM14Y2baCkBAoK/I7EGGNqXajG7D38WJNoLCKl07gJrvtDSriDixqBfSlKl40xJkaEaqNIrstAopr1pTDGxLAKTz2JSNPKnlyVMvWCTYlqjIlhodoo3hCRB0RkiIg0Kd0oIp1F5Bci8h5wevhDjAKJiZCSYjUKY0xMCnXqaYSInAH8EjjFmzPiELAOeBuYqKrf102YUcDmpTDGxKiQQ3io6ixgVh3FEt1SUyEvz+8ojDGm1tnlsbWltEah1uXEGBNbLFHUltRUN3nR3r1+R2KMMbXKEkVtKb3yydopjDExpipzZj8gIr3qIpioZonCGBOjqlKjWAM8JSKLROQabxIjU15ppzvrS2GMiTGVJgpVfUZVTwEuBdKA5SLysojU1iRGsSElBRISrEZhjIk5VWqjEJE4oId32w58DvxaRKaFMbboIuJOP1miMMbEmEqnQhWRB4GzgbnAn1X1M++h+0RkXTiDizqWKIwxMajSRAEsB+5S1X1BHhtYy/FEt9RUyM6uvJwxxkSRqiSKz4HuIhK4bRfwtaruCktU0apNG9ixA4qKoGFDv6MxxphaUZVE8Q+gP65mIUBvYBXQTESuVdXZYYwvupReIrt9O7Rr528sxhhTS6rSmP0d0E9Vs1Q1E+gHbABGAX8JZ3BRx/pSGGNiUFUSRTdVXVW6oqqrgR6quiF8YUUpSxTGmBhUlVNPq0XkcaD0Utjx3rZEoChskUWj1q3dZbKWKIwxMaQqNYqJwJfAzd5tA3AZLklUq9OdiLQUkfdFZL1336KCch1FZLaIrBGR1SKSVp3j1ZmGDaFFC+udbYyJKSFrFF5Hu1mqehrwQJAi1R0qdRIwV1XvFZFJ3vodQcpNBf6kqu97066WVPN4dcf6UhhjYkzIGoWqFgMlYRjfaSzworf8IjCufAERSQfiVfV9L5a9qrq/luOofZYojDExpiptFHuBFSLyPlDW6U5Vb6zBcduq6mZv+XugbZAy3YCdIvIfoBMwB5jkJa/IlZoKn33mJjA6vO+JMcZEpaokiv94t6MiInOAY4I89JvAFVVVEQk2LVw8MBh3Oe43wCu4tpFngxzrauBqgI4dOx5tqLWrTRsoLITdu6GZDbRrjIl+lSYKVX1RRBoBHVW1ymM7qerIih4TkS0i0k5VN4tIOyBY628esKz0MlwReR0YRJBEoapPAU8BZGVl+TsXaeklslu3WqIwxsSEqkxcdDawDHjXW88QkZk1PO5M3NVUePdvBCmzGGguIt43L8OB1TU8bvhZXwpjTIypyuWxk3GD/+0EUNVlQOcaHvdeYJSIrAdGeuuISJaIPOMdpxi4FZgrIitww4c8XcPjhl/pBEaWKIwxMaIqbRRFqrqr3KCANbpMVVXzgRFBtmcDVwasvw/0qcmx6lyTJpCUZH0pjDExoyqJYpWIXALEiUhX4EZgYXjDimI2gZExJsZU5dTTDUAv4CDwb2A3roe2qUibNpYojDExoypXPe3HXdL6m8rKGk9qKqxf73cUxhhTK6oyFWo3XKNyWmB5VR0evrCiXJs2rh/FwYOQmOh3NMYYUyNVaaP4P+AJ4BkgsntFR4rACYzat/c3FmOMqaGqJIpDqvp42COJJYGd7ixRGGOiXFUas98Ukf8VkXbe8OAtRaRl2COLZtaXwhgTQ6pSoyjtQX1bwDal5p3uYlfLljaBkTEmZlTlqqdOdRFITImLg1atYMsWvyMxxpgaq/DUk4jcHrB8YbnH/hzOoGJCp06wdq3fURhjTI2FaqO4KGD5znKPnR6GWGJL//6webO7GWNMFAuVKKSC5WDrprzMTHe/dKm/cRhjTA2FShRawXKwdVNeu3bulpPjdyTGGFMjoRqz+4rIblztoZG3jLeeFPbIYkG/fvDBB3DoEMRX5QIzY4yJPBXWKFQ1TlVTVDVZVeO95dL1hnUZZNTKzIQDB2B15M+3ZIwxFalKhztTXX36uJrEkiV+R2KMMdVmiSKckpIgPd3aKYwxUc0SRbj17w+5uVBQ4HckxhhTLZYowq1/f3dvl8kaY6KUJYpwS0uDFi3s9JMxJmpZogg3EVerWLYMSkr8jsYYY46aJYq60L8/7Nlj06MaY6KSJYq60K+fq1lkZ/sdiTHGHDVLFHUhORl694YFC0Bt9BNjTHTxJVF4s+S9LyLrvfsWFZT7i4isEpE1IvKwiETvYITDhsG338JXX/kdiTHGHBW/ahSTgLmq2hWY660fRkR+ApwC9AF6AwOAoXUZZK36yU9cL+0PP/Q7EmOMOSp+JYqxwIve8ovAuCBlFDf4YAKQCDQEonfKuKZN3dhPH31kVz8ZY6KKX4miraqWzujzPdC2fAFV/S8wD9js3d5T1TXBdiYiV4tItohkb4vkeaqHDXM9tFeu9DsSY4ypsrAlChGZIyIrg9zGBpZTVSXI/BYi0gXoCXQA2gPDRWRwsGOp6lOqmqWqWampqWH4a2rJwIHQqBHMn+93JMYYU2VhmyRBVUdW9JiIbBGRdqq6WUTaAVuDFDsX+FRV93rPeQc4GVgQloDrQkKCa6tYuBCuucatG2NMhPPr1NNMYKK3PBF4I0iZb4ChIhIvIg1xDdlBTz1FlaFDYd8+G9LDGBM1/EoU9wKjRGQ9MNJbR0SyROQZr8x04CtgBfA58LmqvulHsLWqTx9o1sxOPxljooYv83Oqaj4wIsj2bOBKb7kY+GUdhxZ+cXEwZAi8+66rWTRp4ndExhgTkvXM9sPQoVBUZH0qjDFRwRKFH7p1g+7d4bXX4NAhv6MxxpiQLFH4QQQuvhi2boW5c/2OxhhjQrJE4Zf+/V3N4tVXrVZhjIlolij8IgKXXOJqFR984Hc0xhhTIUsUfurfH7p2hVdesVqFMSZiWaLwU2CtYt48v6MxxpigLFH4LTPTahXGmIhmicJvIjBhAmzZAr//vZtb2xhjIoglikiQmQk33wyrV8Mtt8CmTX5HZIwxZSxRRIoRI+DPf4YffnDJYvFivyMyxhjAEkVk6dkTHnwQ2rWDe+6BNdE/WK4xJvpZoog0rVvDlCnQpg088ADs3+93RMaYes4SRSRq3Nidftq6FZ56yu9ojDH1nCWKSNWzJ/zsZ24sqE8+8TsaY0w9Zokikl10ketj8dhjkJ/vdzTGmHrKEkUki493p6AKC+GRR/yOxhhTT1miiHTt27shyXNyIDfX72iMMfWQJYpoMGqUq128/77fkRhj6iFLFNEgJQUGDXIDBxYV+R2NMaaesUQRLUaNcuNALVrkdyTGmHrGEkW0yMhwnfHs9JMxpo7F+x2AqaIGDWDkSDcc+bZtkJpateft3g0PPwyJiXDsse7WqROkpYU1XGNM7LAaRTQZORJUXSe8qlCFhx5yV0ytXeuSzN/+BjfcALNmhTdWY0zM8CVRiMiFIrJKREpEJCtEudNFZJ2IfCkik+oyxojUti307etOP6lWXn7WLPjsM7jsMnj2WXjtNfjHP2DAAHjiCZdAjDGmEn7VKFYC5wEfVVRAROKAx4CfAunAxSKSXjfhRbDRo90YUMuXhy6Xm+uSQ2YmnHOO29awIRx3HNx+uzv9dO+9sHFj2EM2xkQ3XxKFqq5R1XWVFBsIfKmqG1S1EJgGjA1/dBFu0CBo2hTeeafiMoWFcP/90KSJmxBJ5PDHk5Lgd79zj999NxQUhDVkY0x0i+Q2ivZA4FRved62I4jI1SKSLSLZ27Ztq5PgfJOQAGed5QYKXLgweJlnn4VvvoFf/QqaNw9eplUrlyz27nXJ4sCBsIVsjIluYUsUIjJHRFYGudV6rUBVn1LVLFXNSq3q1UDRbPx46NbNXc1UPjFOn+7aJs49F/r3D72fzp3daagNG1wNpKQkfDEbY6JW2BKFqo5U1d5Bbm9UcRffAscFrHfwtpn4eLj1VvfF/te/QnGx2/7mm/DiizBkiGvArooBA+Caa1yj9zPPhC1kY0z0iuRTT4uBriLSSUQSgIuAmT7HFDnatYPrroPVq91lr+++6yY5Ovlkd8qpwVG8tWecAePGuUQz015iY8zhfOlwJyLnAo8AqcDbIrJMVceIyLHAM6p6hqoeEpHrgfeAOOA5VV3lR7wRa+hQWLoUpk1z61lZ7lRSfDXe1iuucFdTPfOMm4Z10KDajdUYE7VEq3I9fhTJysrS7Oxsv8OoOz/8ALfd5ob3+H//zzV2V9fBg/Cb37hLax94AI4/vtbCNMZENhHJUdWg/dosUcSCkhJ3CWz5y2Cro6DAXVLbqJHrxd2kSc33aYyJeKESRSS3UZiqatCgdpIEQMuWMGkSbNkCDz5YtR7gxpiYZonCHCk93bVZLFrkhv0wxtRrlihMcGef7S6znToVli3zOxpjjI9smHETnIgbZTY3140Jde+9lQ9NXlgIc+a4oc2Li90tKQnOPNPaOoyJYtaYbULbutVdcqsKf/mLG8E2mG3bYMoUWL/+x23x8XDokLvc9vbboXv3uonZGHPUrDHbVF+bNm4sqMJC+O1vYdeuI8t8/rm7Uurbb+Guu2DGDNdxb8YM13Mc4I474D//scZxY6KQ1ShM1axd6/pYdOgAN94I+/a5U0wbNrjxpTp0cI+3DzJu4759blyqhQvdlK7jx0OvXsGv1Dp0yA19vmYNfPGFuwrrpJOgZ8+j621ujDkq1o/C1I6cHLjnnh/Hlip16qkueTRqVPFzVd0wI1OnuhFrO3VyDeY9e7pk88UX7vbVV672Ai5J7N7tkkdKCgwcCOed5+bUMMbUKksUpvZs2ACbN7sv7pQUaNas4qHMgzl4ED780I0rlZv74/aEBDeabbduLnn06OF6m+/fD0uWwKefwuLFUFQEl14KY8fWXt8RY4wlChOBVGHVKpd0TjgBOnasfIyqnTvh0Udd/47evV27SEWN60ejuNjtOz4ekpPtFJeplyxRmNihCh984EbKLSlxp6LOOafql98WFLhpZJcvd5M7bd/utpX+H4i4mlKLFtC1q2tT6dvX1ZyMiWGWKEzs2bYNnn4a/vtfNzXseee5No+kpMPL7doFK1fCihUuOWzyJk1MTnbtJKmp7hRXq1auLWT3ble7yM93Q7jv2+fKd+7shnAfPDh4g70xUc4ShYldX34JL7/s2i8SE90v/0aNXMLYv//HxJCU5IYm6dvX3Tp3rryNo6TE7X/ZMsjOdldigXvuKafAiSe602ahRuxVdYln61aXfLZvd/cHD7pTXiUlrkzDhi7+xEQXf3Kyu5W2A7VqdWQSNKYWWaIwsW/dOtdIvm+fm/97/37X5pCe7r7Qu3Sp3jwdgbZvd3OVL1jgjgdun6VtLHFxP5bdswe++861wZSfj7xhQ/el36CBe46Ia6Q/eNDdKtKkiasBtWrlrghr1crdUlLcPhs2dEmruNgNPx9427/f3X744fDRhhs0cM9JTHT3CQkuptJbaXtN6cCT8fE/lk9MdH9HUtKPyTk+/sfnirhjFRe72lpxsfs7S2+l20pvpccpfV0Ck2diolsPfI1NrQqVKGwIj3LuvBNGjoQRI9zn+Le/hdGj4bTT3P/w5MluQrjBg9130h//6M54/OQn7qzFlCluuuqBA2HHDteZ+YILIDPTfc888IDrRpCRAd9/Dw89BBMmuLbZb791bbWXXuou/Pn6a3jiCTc+X9eu7oKjp5+Gq65yP2rXr4fnnnMzmR5/vPvBO3UqXH+9OzuyciW89BLcdBMcc4z7YfzKK3DLLe5sS06O6wJx++3ulPxnn7k+cnfe6b57Fi50FyfddZf7jlqwwE3HPXmy+7+dNw9mz3ZXzMbHw9y5bgSPKVPca/nee+45f/yjW581yx1j8mS3PnOm66v329+69RkzXHeNO+9069Onu7/59tvd+rRp7jW65Ra3/tJL7gzUzTcD3bvz4qfd2VMI1//KPf7cc3BwO1zbw60//bS7v+oqd//44+7vuOIKt/7oo+5H/MSJbv3vf3ffyxMmuPUHXmxN+/ZjueivY2HXLv7ym1101q+4IO5dyM5myoqz6NFsM+d2zIHGjbnni/H07VnIOT8tgrZtmfyvLgwcnMgZ5zcCEe66y32OxowJ+OyNUEacepBDO/bw2z/EMzozn9O65nFwcwGTX0zjjKYrGLxzKfvW5fHH7NM5u81cftJyLbuLGjHlyws595j/MrDFenYUNuEvX53PBe0+IbP5V2wvTOGBTRcyvssSMlpt4vv9KTy0ehQT0j6hd5ONfLuzCY9+eTqXdphDz+Q8vt6fyhNf/5Qrjnufrk03s2FfW57+ZgxXdXyPzk22sH5vO57bNIprjn+H4xtvY82eDkzNG871aW/RvlEBK3d35KVvh3FTp5kck7STZbs68cp3g7nlhNdpnbCbnJ0nMH3zKdx+wmu0SNjHZzu6MuP7k7mzy/+R0vAHFhb04M0tA7mr6ys0iT/Igvx0Zm3NYnL3f5OYJMwr6MvsLX25p/crxDcoYe6W3szZ3Ispvf4FJSW8t6UvC/LT+WPPl91nb0smn+3oyuT0V0GEmd9l8fnuTvy253QQYca3A1m7+1ju7DHDffbyBrFhX1tu7+5mbp6WdwrfHmjNLenvgAgvfX0q2w6mcHPvOdCgAS9+eQp7ihK5vtd899lb+xMOFsdzbfcP3Gdv7WD32esyz332vhhBYoMirujykfvsrRtFcsIBJnZZCCL8ffVoUhvtYUKXz0CEB1aMpn2TnVx0wmIQ4S/LRtM5ZTsXdMoBYMqy0+nR7HvOHb7rx3+gWmSJwpjqaNYMOjaDzh3hgtPctilAD+Bcr8w9QF/gLG/9baAxEOqMl4j7ZZ6aBC2ALi1gWBc4CCwHzugPgyfCPuDuEhg6EtJ3wo5i+EczGNoX+h6Eg43hhTZw7ig4JQn2JMLfBMaPgwzge+AhYMJZ0Bs3G/0jChedA92KYWMJPBsPF4+CzsWwUWBqIlwyFI7ZD18ovNoEzukGLXbDugbwbiqMbgzN98HXybCgI5zREFofgm9awsLj4IIW0BrY0AIWtIVLO7m/c00yzGsGE7tA40OwNAk+ag7jW0GDH2BpU1icCmPPBw7CqlRY3cH9gotTWHMsNOrgxhWLi4OV7eGLtnD++e51XXYsfNXKXVZdUgJLO8Cmlu5XnyosTYPNzdw6QHYabEuGnxa59U/TYEcjN6tkSQk07AK7E91pzJIS2H8sHExwv/BUYfexUNLQPS4CB9LcfkpnjixKg/gSGOT1GTpwPCQWQv8D3unKY6HJfkjf69a/T4VmSe4XI0Bea2gZ79ZF3HqbOPeZDAM79WSMMcbGejLGGFN9liiMMcaEZInCGGNMSJYojDHGhGSJwhhjTEiWKIwxxoRkicIYY0xIliiMMcaEFHMd7kRkG/D1UTylNbA9TOHURKTGBZEbW6TGBZEbW6TGBRZbddQkruNVNTXYAzGXKI6WiGRX1BvRT5EaF0RubJEaF0RubJEaF1hs1RGuuOzUkzHGmJAsURhjjAnJEgU85XcAFYjUuCByY4vUuCByY4vUuMBiq46wxFXv2yiMMcaEZjUKY4wxIVmiMMYYE1K9TRQicrqIrBORL0Vkks+xPCciW0VkZcC2liLyvois9+5b+BDXcSIyT0RWi8gqEbkpgmJLEpHPRORzL7Y/eNs7icgi7319RUQS6jo2L444EVkqIm9FWFy5IrJCRJaJSLa3LRLez+YiMl1E1orIGhE5OULi6u69VqW33SJyc4TE9ivvs79SRP7t/U+E5XNWLxOFiMQBjwE/BdKBi0Uk3ceQXgBOL7dtEjBXVbsCc731unYIuEVV04FBwHXe6xQJsR0EhqtqX9zknqeLyCDgPuBBVe0C7AB+4UNsADcBawLWIyUugNNUNSPgevtIeD8fAt5V1R64CWTXREJcqrrOe60ygExgPzDD79hEpD1wI5Clqr2BOOAiwvU5U9V6dwNOBt4LWL8TuNPnmNKAlQHr64B23nI7YF0EvG5vAKMiLTbcTNRLgJNwvVLjg73PdRhPB9yXx3DgLdws2b7H5R07F2hdbpuv7yfQDNiId3FNpMQVJM7RwCeREBvQHtgEtATivc/ZmHB9zupljYIfX+RSed62SNJWVTd7y98Dbf0MRkTSgH7AIiIkNu/0zjJgK/A+8BWwU1UPeUX8el//DtwOlHjrrSIkLgAFZotIjohc7W3z+/3sBGwDnvdO1z0jIk0iIK7yLgL+7S37Gpuqfgv8FfgG2AzsAnII0+esviaKqKLu54Fv1zGLSFPgNeBmVd0d+JifsalqsbpTAh2AgUAPP+IIJCJnAVtVNcfvWCpwqqr2x512vU5EhgQ+6NP7GQ/0Bx5X1X7APsqdyomA/4EE4Bzg/8o/5kdsXpvIWFySPRZowpGnr2tNfU0U3wLHBax38LZFki0i0g7Au9/qRxAi0hCXJF5S1f9EUmylVHUnMA9X1W4uIvHeQ368r6cA54hILjANd/rpoQiICyj7JYqqbsWdax+I/+9nHpCnqou89em4xOF3XIF+CixR1S3eut+xjQQ2quo2VS0C/oP77IXlc1ZfE8VioKt3hUACrko50+eYypsJTPSWJ+LaB+qUiAjwLLBGVf8WYbGlikhzb7kRru1kDS5hXOBXbKp6p6p2UNU03OfqA1Wd4HdcACLSRESSS5dx59xX4vP7qarfA5tEpLu3aQSw2u+4yrmYH087gf+xfQMMEpHG3v9p6WsWns+Zn41Dft6AM4AvcOe1f+NzLP/GnWcswv26+gXuvPZcYD0wB2jpQ1yn4qrUy4Fl3u2MCImtD7DUi20l8Dtve2fgM+BL3GmCRB/f12HAW5ESlxfD595tVennPkLezwwg23s/XwdaREJcXmxNgHygWcA232MD/gCs9T7//wQSw/U5syE8jDHGhFRfTz0ZY4ypIksUxhhjQrJEYYwxJiRLFMYYY0KyRGGMMSYkSxQmqoiIisgDAeu3isjkWtr3CyJyQeUla3ycC70RUueV236siEz3ljNE5IxaPGZzEfnfYMcypjKWKEy0OQicJyKt/Q4kUEBv2Kr4BXCVqp4WuFFVv1PV0kSVgeuzUlsxNAfKEkW5YxkTkiUKE20O4eYF/lX5B8rXCERkr3c/TEQ+FJE3RGSDiNwrIhPEzWexQkROCNjNSBHJFpEvvHGbSgcfvF9EFovIchH5ZcB+F4jITFyv2PLxXOztf6WI3Odt+x2uI+OzInJ/ufJpXtkE4G5gvDcHwnivV/VzXsxLRWSs95zLRGSmiHwAzBWRpiIyV0SWeMce6+3+XuAEb3/3lx7L20eSiDzvlV8qIqcF7Ps/IvKuuHkX/nLU75aJCUfzK8iYSPEYsPwov7j6Aj2BAmAD8IyqDhQ3GdMNwM1euTTc+EcnAPNEpAtwKbBLVQeISCLwiYjM9sr3B3qr6sbAg4nIsbi5ATJx8wLMFpFxqnq3iAwHblXV7GCBqmqhl1CyVPV6b39/xg0HcoU3dMlnIjInIIY+qlrg1SrOVdXdXq3rUy+RTfLizPD2lxZwyOvcYfVEEenhxdrNeywDN2rwQWCdiDyiqoEjL5t6wGoUJuqoG8F2Km7ilqparKqbVfUgbtiW0i/6FbjkUOpVVS1R1fW4hNIDNybSpeKGNF+EG76hq1f+s/JJwjMAmK9u0LZDwEvAkCDlqmo0MMmLYT6QBHT0HntfVQu8ZQH+LCLLcUNLtKfyIbBPBf4FoKprga+B0kQxV1V3qeoBXK3p+Br8DSZKWY3CRKu/4yYrej5g2yG8Hz8i0gAInAbyYMByScB6CYf/H5Qf00ZxX743qOp7gQ+IyDDckNh1QYDzVXVduRhOKhfDBCAVyFTVInGj2CbV4LiBr1sx9p1RL1mNwkQl7xf0qxw+1WMu7lQPuLkDGlZj1xeKSAOv3aIzbiaz94BrxQ25joh080ZfDeUzYKiItBY39e7FwIdHEcceIDlg/T3gBm+kUESkXwXPa4abD6PIa2sorQGU31+gBbgEg3fKqSPu7zYGsERhotsDQODVT0/jvpw/x81NUZ1f+9/gvuTfAa7xTrk8gzvtssRrAH6SSn5Zq5v9bBJu2OfPgRxVPZohn+cB6aWN2cA9uMS3XERWeevBvARkicgKXNvKWi+efFzbysryjejAP4AG3nNeAS7zTtEZA2CjxxpjjAnNahTGGGNCskRhjDEmJEsUxhhjQrJEYYwxJiRLFMYYY0KyRGGMMSYkSxTGGGNC+v8Xsrcupbe9vwAAAABJRU5ErkJggg==\n",
"image/png": "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vokpU6Ywf/786vKmTZvYsmULBx54YPW6yZMnM3v2bCZNmgTAxo0bWbx4Mbm5uQwfPpwePXoAUFxczLJly6onfDrllFOAUCMpiDeFA+eddx4AGzZsYPPmzRx77LEAXHjhhbz44osAnHvuudx8883ccccdPPzww/vl7vSohvC4AZjq7rea2Q2x8vV17Hsz0PQjbxUUKFFIs3bLLbuft25ds9y2bc1y+/Y1yx071ix36lT/+YqKiqp/+AHuvfde1q1bR0lJScJ52td7nNatW7Nr167qcuKkQm3btq1+npOTU930VJdLL72Ujz/+mEMPPZSXX36Zl156ibfeeosXXniB//3f/2XOnDl7vOaqq67ixz/+MWeccQbTp09n/PjxSY+9a9cu3n///T0mVErk7tx9992MGTOmxvrp06fv8W+prKzE3SkqKuJvf/tb0uOl8/61a9eOU045heeee46nnnoq5fhW6Yqqj+JM4LHY88eAscl2MrNhwCHA5KYJK4HmpRDZK6NGjWLbtm1MmDChet0XX3xR5/7HH388TzzxBBB+OLt27UrHjh0pLCzko48+AuCjjz5i6dKlKc+bn59Pfn5+9XwS8WMCPPLII8yaNYuXX36ZXbt2sWLFCk488URuu+02Nm7cyJYtW+jQoQObE65w3LhxI4cddhgAjz32WPX62vuNHj2au+++u7qc2C8QN2bMGCZMmMDOnTsB+Pvf/87WrVvr/Lf07duXtWvXVieKnTt3Mm/evKT/5g4dOvDBBx8AMHHixBrbL7vsMq6++mpKS0vplE6Wr0dUieIQd4//Cn9OSAY1mFkr4E7guvoOZmbfNbMyMytbu3bt/omwoAAqKsJIsiJSLzPj2Wef5c0336Rnz54MHz6cSy65hNtuuy3p/uPHj2fmzJkMGjSIG264ofpH+ZxzzqGiooKioiLuueeetIYYf+SRR7jiiisoLi6u7hSuraqqim9961sMHDiQIUOGcPXVV5Ofn883vvENnnnmmepO6vHjx3PuuecybNgwuiYMDFp7v9/97neUlZUxaNAgBgwYwH333bfHOS+77DIGDBjA0KFDOfroo/ne976X8oql3NxcJk2axPXXX8/gwYMpLi6u80qrP/zhD1x++eUUFxezdetWDjrooOptw4YNo2PHjlx66aX1vnfpsLre1AYf2GwKsOdUU3AT8Ji75yfsu97d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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
......@@ -562,10 +576,9 @@
"\n",
"Recall the above calculation is done with an interatomic distance $d = 74$ pm between two hydrogen atoms. Another interesting aspect we can try with VQE is determining the true interatomic distance by modifying the `h2.xyz` file. The results are summarize in figure below,\n",
"\n",
"![VQE-fig-dist](figures/VQE-fig-distance.png)\n",
"![vqe-fig-dist](figures/vqe-fig-distance.png)\n",
"\n",
"The lowest value is found around $d = 74$ pm (1 pm = $1\\times 10^{-12}$m), which is consistent with the [experimental data](https://cccbdb.nist.gov/exp2x.asp?casno=1333740&charge=0) $d_{exp} (H_2) = 74.14$ pm.\n",
"\n"
"The lowest value is found around $d = 74$ pm (1 pm = $1\\times 10^{-12}$m), which is consistent with the [experimental data](https://cccbdb.nist.gov/exp2x.asp?casno=1333740&charge=0) $d_{exp} (H_2) = 74.14$ pm."
]
},
{
......@@ -576,7 +589,6 @@
"\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",
"[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",
......@@ -586,12 +598,11 @@
"\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",
"[5] Helgaker, Trygve, Poul Jorgensen, and Jeppe Olsen. Molecular electronic-structure theory. John Wiley & Sons, 2014.\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",
"\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."
]
}
],
......@@ -611,7 +622,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......@@ -629,7 +640,7 @@
"width": "426.667px"
},
"toc_section_display": true,
"toc_window_display": true
"toc_window_display": false
}
},
"nbformat": 4,
......
......@@ -6,8 +6,13 @@
"source": [
"# 变分量子态对角化算法\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>\n",
"\n",
"<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 概览\n",
"\n",
"- 在本案例中,我们将通过 Paddle Quantum 训练量子神经网络来完成量子态的对角化\n",
......@@ -20,8 +25,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:19.668798Z",
"start_time": "2021-03-09T03:43:16.454757Z"
"end_time": "2021-04-30T09:17:03.603558Z",
"start_time": "2021-04-30T09:17:00.931471Z"
}
},
"outputs": [],
......@@ -42,7 +47,7 @@
"metadata": {},
"source": [
"## 背景\n",
"量子态对角化算法(Variational Quantum State Diagonalization, VQSD)[1-3] 目标是输出一个量子态的本征谱,即其所有本征值。求解量子态的本征值在量子计算中有着诸多应用,比如可以用于计算保真度和冯诺依曼熵,也可以用于主成分分析。\n",
"量子态对角化算法(variational quantum state diagonalization, VQSD)[1-3] 目标是输出一个量子态的本征谱,即其所有本征值。求解量子态的本征值在量子计算中有着诸多应用,比如可以用于计算保真度和冯诺依曼熵,也可以用于主成分分析。\n",
"- 量子态通常是一个混合态,表示如下 $\\rho_{\\text{mixed}} = \\sum_i P_i |\\psi_i\\rangle\\langle\\psi_i|$\n",
"- 作为一个简单的例子,我们考虑一个 2 量子位的量子态,它的本征谱为 $(0.5, 0.3, 0.1, 0.1)$,我们先通过随机作用一个酉矩阵来生成具有这样本征谱的随机量子态。"
]
......@@ -52,8 +57,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:19.692450Z",
"start_time": "2021-03-09T03:43:19.672516Z"
"end_time": "2021-04-30T09:17:03.622120Z",
"start_time": "2021-04-30T09:17:03.609542Z"
}
},
"outputs": [
......@@ -94,8 +99,8 @@
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:23.035187Z",
"start_time": "2021-03-09T03:43:23.015744Z"
"end_time": "2021-04-30T09:17:03.646986Z",
"start_time": "2021-04-30T09:17:03.637134Z"
}
},
"outputs": [],
......@@ -113,8 +118,8 @@
" cir = UAnsatz(N)\n",
" # 调用内置的量子神经网络模板\n",
" cir.universal_2_qubit_gate(theta, [0, 1])\n",
" # 返回量子神经网络所模拟的酉矩阵 U\n",
" return cir.U"
" # 返回量子神经网络的电路\n",
" return cir"
]
},
{
......@@ -132,8 +137,8 @@
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:25.122460Z",
"start_time": "2021-03-09T03:43:25.109448Z"
"end_time": "2021-04-30T09:17:03.676479Z",
"start_time": "2021-04-30T09:17:03.660557Z"
}
},
"outputs": [],
......@@ -164,15 +169,16 @@
" def forward(self, N):\n",
" \n",
" # 施加量子神经网络\n",
" U = U_theta(self.theta, N)\n",
"\n",
" cir = U_theta(self.theta, N)\n",
" U = cir.U\n",
" \n",
" # rho_tilde 是将 U 作用在 rho 后得到的量子态 U*rho*U^dagger \n",
" rho_tilde = matmul(matmul(U, self.rho), dagger(U))\n",
"\n",
" # 计算损失函数\n",
" loss = trace(matmul(self.sigma, rho_tilde))\n",
"\n",
" return paddle.real(loss), rho_tilde"
" return paddle.real(loss), rho_tilde, cir"
]
},
{
......@@ -189,8 +195,8 @@
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:26.181791Z",
"start_time": "2021-03-09T03:43:26.175799Z"
"end_time": "2021-04-30T09:17:04.114466Z",
"start_time": "2021-04-30T09:17:04.099242Z"
}
},
"outputs": [],
......@@ -215,8 +221,8 @@
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:32.881935Z",
"start_time": "2021-03-09T03:43:31.477330Z"
"end_time": "2021-04-30T09:17:10.042819Z",
"start_time": "2021-04-30T09:17:08.580527Z"
}
},
"outputs": [
......@@ -228,7 +234,13 @@
"iter: 10 loss: 0.1958\n",
"iter: 20 loss: 0.1843\n",
"iter: 30 loss: 0.1816\n",
"iter: 40 loss: 0.1805\n"
"iter: 40 loss: 0.1805\n",
"\n",
"训练后的电路:\n",
"--U----X----Rz(1.489)----*-----------------X----U--\n",
" | | | \n",
"--U----*----Ry(1.367)----X----Ry(2.749)----*----U--\n",
" \n"
]
}
],
......@@ -246,7 +258,7 @@
"for itr in range(ITR):\n",
"\n",
" # 前向传播计算损失函数并返回估计的能谱\n",
" loss, rho_tilde = net(N)\n",
" loss, rho_tilde, cir = net(N)\n",
" rho_tilde_np = rho_tilde.numpy()\n",
"\n",
" # 反向传播极小化损失函数\n",
......@@ -256,7 +268,10 @@
"\n",
" # 打印训练结果\n",
" if itr % 10 == 0:\n",
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])"
" print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])\n",
" if itr == ITR - 1:\n",
" print(\"\\n训练后的电路:\")\n",
" print(cir)"
]
},
{
......@@ -273,8 +288,8 @@
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:34.374882Z",
"start_time": "2021-03-09T03:43:34.365530Z"
"end_time": "2021-04-30T09:17:13.536415Z",
"start_time": "2021-04-30T09:17:13.527756Z"
}
},
"outputs": [
......@@ -324,7 +339,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.7.0"
},
"toc": {
"base_numbering": 1,
......
......@@ -20,8 +20,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:45.281082Z",
"start_time": "2021-03-09T03:43:42.268516Z"
"end_time": "2021-04-30T09:16:42.117977Z",
"start_time": "2021-04-30T09:16:38.578847Z"
}
},
"outputs": [],
......@@ -58,8 +58,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:45.305154Z",
"start_time": "2021-03-09T03:43:45.283902Z"
"end_time": "2021-04-30T09:16:42.139676Z",
"start_time": "2021-04-30T09:16:42.121581Z"
}
},
"outputs": [
......@@ -100,8 +100,8 @@
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:45.326631Z",
"start_time": "2021-03-09T03:43:45.319403Z"
"end_time": "2021-04-30T09:16:42.152252Z",
"start_time": "2021-04-30T09:16:42.144220Z"
}
},
"outputs": [],
......@@ -118,8 +118,8 @@
" cir = UAnsatz(N)\n",
" # Call the built-in quantum neural network template\n",
" cir.universal_2_qubit_gate(theta, [0, 1])\n",
" # Return the unitary matrix U simulated by the quantum neural network\n",
" return cir.U"
" # Return the circuit of the quantum neural network\n",
" return cir"
]
},
{
......@@ -147,8 +147,8 @@
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:45.348068Z",
"start_time": "2021-03-09T03:43:45.329388Z"
"end_time": "2021-04-30T09:16:42.172611Z",
"start_time": "2021-04-30T09:16:42.155186Z"
}
},
"outputs": [],
......@@ -179,7 +179,8 @@
" def forward(self, N):\n",
" \n",
" # Apply quantum neural network\n",
" U = U_theta(self.theta, N)\n",
" cir = U_theta(self.theta, N)\n",
" U = cir.U\n",
"\n",
" # rho_tilde is the quantum state U*rho*U^dagger \n",
" rho_tilde = matmul(matmul(U, self.rho), dagger(U))\n",
......@@ -187,7 +188,7 @@
" # Calculate the loss function\n",
" loss = trace(matmul(self.sigma, rho_tilde))\n",
"\n",
" return paddle.real(loss), rho_tilde"
" return paddle.real(loss), rho_tilde, cir"
]
},
{
......@@ -204,8 +205,8 @@
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:46.380433Z",
"start_time": "2021-03-09T03:43:46.376425Z"
"end_time": "2021-04-30T09:16:42.468056Z",
"start_time": "2021-04-30T09:16:42.457529Z"
}
},
"outputs": [],
......@@ -229,8 +230,8 @@
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:52.935466Z",
"start_time": "2021-03-09T03:43:51.655041Z"
"end_time": "2021-04-30T09:16:50.340636Z",
"start_time": "2021-04-30T09:16:48.778551Z"
}
},
"outputs": [
......@@ -242,7 +243,13 @@
"iter: 10 loss: 0.1958\n",
"iter: 20 loss: 0.1843\n",
"iter: 30 loss: 0.1816\n",
"iter: 40 loss: 0.1805\n"
"iter: 40 loss: 0.1805\n",
"\n",
"The trained circuit:\n",
"--U----X----Rz(1.489)----*-----------------X----U--\n",
" | | | \n",
"--U----*----Ry(1.367)----X----Ry(2.749)----*----U--\n",
" \n"
]
}
],
......@@ -260,7 +267,7 @@
"for itr in range(ITR):\n",
"\n",
" # Forward propagation calculates the loss function and returns the estimated energy spectrum\n",
" loss, rho_tilde = net(N)\n",
" loss, rho_tilde, cir = net(N)\n",
" rho_tilde_np = rho_tilde.numpy()\n",
"\n",
" # Back propagation minimizes the loss function\n",
......@@ -270,7 +277,10 @@
"\n",
" # Print training results\n",
" if itr% 10 == 0:\n",
" print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])"
" print('iter:', itr,'loss:','%.4f'% loss.numpy()[0])\n",
" if itr == ITR - 1:\n",
" print(\"\\nThe trained circuit:\")\n",
" print(cir)"
]
},
{
......@@ -287,8 +297,8 @@
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-03-09T03:43:54.017576Z",
"start_time": "2021-03-09T03:43:54.008564Z"
"end_time": "2021-04-30T09:16:52.099611Z",
"start_time": "2021-04-30T09:16:52.087176Z"
}
},
"outputs": [
......@@ -339,7 +349,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
"version": "3.8.3"
},
"toc": {
"base_numbering": 1,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册