提交 016af983 编写于 作者: Q Quleaf

update to v2.1.3

上级 ba95036b
......@@ -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 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.
[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 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.1.2-orange.svg?style=flat-square&logo=pypi"/>
<img src="https://img.shields.io/badge/pypi-v2.1.3-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 (37+ tutorials)
- Many online learning resources (Nearly 40 tutorials)
- High efficiency in building QNN with various QNN templates
- Automatic differentiation
- Versatile
......@@ -71,7 +71,7 @@ Paddle Quantum aims at establishing a bridge between artificial intelligence (AI
### Install PaddlePaddle
This dependency will be automatically satisfied when users install Paddle Quantum. Please refer to [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick)'s official installation and configuration page. This project requires PaddlePaddle 2.1.1+.
This dependency will be automatically satisfied when users install Paddle Quantum. Please refer to [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick)'s official installation and configuration page. This project requires PaddlePaddle 2.2.0+.
### Install Paddle Quantum
......@@ -90,20 +90,14 @@ pip install -e .
### Environment setup for Quantum Chemistry module
Our `qchem` module is based on `Openfermion` and `Psi4`, so before executing quantum chemistry, we have to install the two Python packages first.
Our `qchem` module is based on `Psi4`, so before executing quantum chemistry, we have to install this Python package.
> It is recommended that these Python packages be installed in a Python 3.8 environment.
`Openfermion` can be installed with the following command:
```bash
pip install openfermion
```
> It is recommended that `Psi4` is installed in a Python 3.8 environment.
We highly recommend you to install `Psi4` via conda. **MacOS/Linux** user can use the command:
```bash
conda install psi4-c psi4
conda install psi4 -c psi4
```
For **Windows** user, the command is:
......@@ -131,10 +125,13 @@ python main.py
[Paddle Quantum Quick Start Manual](https://github.com/PaddlePaddle/Quantum/tree/master/introduction) is probably the best place to get started with Paddle Quantum. Currently, we support online reading and running the Jupyter Notebook locally. The manual includes the following contents:
- Detailed installation tutorials for Paddle Quantum
- Introduction to the basics of quantum computing and QNN
- Introduction on the operation modes of Paddle Quantum
- A quick tutorial on PaddlePaddle's dynamic computational graph and optimizers
- A case study on Quantum Machine Learning -- Variational Quantum Eigensolver (VQE)
- Introduction to quantum computing and quantum neural networks (QNNs)
- Introduction to Variational Quantum Algorithms (VQAs)
- Introduction to Paddle Quantum
- PaddlePaddle optimizer tutorial
- Introduction to the quantum chemistry module in Paddle Quantum
- How to train QNN with GPU
- Some frequently used functions in Paddle Quantum
### Tutorials
......@@ -150,6 +147,7 @@ We provide tutorials covering quantum simulation, machine learning, combinatoria
7. [Estimation of Quantum State Properties Based on the Classical Shadow](./tutorial/quantum_simulation/ClassicalShadow_Application_EN.ipynb)
8. [Hamiltonian Simulation with Product Formula](./tutorial/quantum_simulation/HamiltonianSimulation_EN.ipynb)
9. [Simulate the Spin Dynamics on a Heisenberg Chain](./tutorial/quantum_simulation/SimulateHeisenberg_EN.ipynb)
10. [Distributed Variational Quantum Eigensolver Based on Schmidt Decomposition](./tutorial/quantum_simulation/DistributedVQE_EN.ipynb)
- [Machine Learning](./tutorial/machine_learning)
1. [Encoding Classical Data into Quantum States](./tutorial/machine_learning/DataEncoding_EN.ipynb)
......@@ -183,6 +181,7 @@ We provide tutorials covering quantum simulation, machine learning, combinatoria
3. [Calculating Gradient Using Quantum Circuit](./tutorial/qnn_research/Gradient_EN.ipynb)
4. [Expressibility of Quantum Neural Network](./tutorial/qnn_research/Expressibility_EN.ipynb)
5. [Variational Quantum Circuit Compiling](./tutorial/qnn_research/VQCC_EN.ipynb)
6. [Quantum Fisher Information](./tutorial/qnn_research/Fisher_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).
......@@ -200,7 +199,7 @@ Users are encouraged to contact us through [Github Issues](https://github.com/Pa
## Research based on Paddle Quantum
We also highly encourage developers to use Paddle Quantum as a research tool to develop novel QML algorithms. If your work uses Paddle Quantum, feel free to send us a notice via quantum@baidu.com. We are always excited to hear that! Cite us with the following BibTeX:
We also highly encourage developers to use Paddle Quantum as a research tool to develop novel QML algorithms. If your work uses Paddle Quantum, feel free to send us a notice via qml@baidu.com. We are always excited to hear that! Cite us with the following BibTeX:
> @misc{Paddlequantum,
> title = {{Paddle Quantum}},
......@@ -209,17 +208,17 @@ 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, 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)]
[1] Wang, Youle, Guangxi Li, and Xin Wang. "Variational quantum Gibbs state preparation with a truncated Taylor series." Physical Review Applied 16.5 (2021): 054035. [[pdf](https://arxiv.org/pdf/2005.08797.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)]
[2] Wang, Xin, Zhixin Song, and Youle Wang. "Variational quantum singular value decomposition." Quantum 5 (2021): 483. [[pdf](https://arxiv.org/pdf/2006.02336.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.
[3] Li, Guangxi, Zhixin Song, and Xin Wang. "VSQL: Variational Shadow Quantum Learning for Classification." Proceedings of the AAAI Conference on Artificial Intelligence. Vol. 35. No. 9. 2021. [[pdf]](https://arxiv.org/pdf/2012.08288.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)
[4] Chen, Ranyiliu, et al. "Variational quantum algorithms for trace distance and fidelity estimation." Quantum Science and Technology (2021). [[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)
[6] Zhao, Xuanqiang, et al. "Practical distributed quantum information processing with LOCCNet." npj Quantum Information 7.1 (2021): 1-7. [[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)
......@@ -257,4 +256,4 @@ Paddle Quantum uses [Apache-2.0 license](LICENSE).
[5] [Schuld, M., Sinayskiy, I. & Petruccione, F. An introduction to quantum machine learning. Contemp. Phys. 56, 172–185 (2015).](https://www.tandfonline.com/doi/abs/10.1080/00107514.2014.964942)
[6] [Benedetti, M., Lloyd, E., Sack, S. & Fiorentini, M. Parameterized quantum circuits as machine learning models. Quantum Sci. Technol. 4, 043001 (2019).](https://iopscience.iop.org/article/10.1088/2058-9565/ab4eb5)
\ No newline at end of file
[6] [Benedetti, M., Lloyd, E., Sack, S. & Fiorentini, M. Parameterized quantum circuits as machine learning models. Quantum Sci. Technol. 4, 043001 (2019).](https://iopscience.iop.org/article/10.1088/2058-9565/ab4eb5)
......@@ -19,7 +19,7 @@
- [Copyright and License](#copyright-and-license)
- [References](#references)
[Paddle Quantum(量桨)](https://qml.baidu.com/)是基于百度飞桨开发的量子机器学习工具集,支持量子神经网络的搭建与训练,提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,使得百度飞桨也因此成为国内首个目前也是唯一一个支持量子机器学习的深度学习框架。
[Paddle Quantum(量桨)](https://qml.baidu.com/)是基于百度飞桨开发的量子机器学习工具集,支持量子神经网络的搭建与训练,提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,使得百度飞桨也因此成为国内首个支持量子机器学习的深度学习框架。
<p align="center">
<a href="https://qml.baidu.com/">
......@@ -34,7 +34,7 @@
</a>
<!-- PyPI -->
<a href="https://pypi.org/project/paddle-quantum/">
<img src="https://img.shields.io/badge/pypi-v2.1.2-orange.svg?style=flat-square&logo=pypi"/>
<img src="https://img.shields.io/badge/pypi-v2.1.3-orange.svg?style=flat-square&logo=pypi"/>
</a>
<!-- Python -->
<a href="https://www.python.org/">
......@@ -55,7 +55,7 @@
## 特色
- 轻松上手
- 丰富的在线学习资源(37+ 教程案例)
- 丰富的在线学习资源(近 40 篇教程案例)
- 通过模板高效搭建量子神经网络
- 自动微分框架
- 功能丰富
......@@ -71,9 +71,9 @@
### 安装 PaddlePaddle
当用户安装 Paddle Quantum 时会自动下载安装这个关键依赖包。关于 PaddlePaddle 更全面的安装信息请参考 [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick) 安装配置页面。此项目需求 PaddlePaddle 2.1.1+。
当用户安装 Paddle Quantum 时会自动下载安装这个关键依赖包。关于 PaddlePaddle 更全面的安装信息请参考 [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick) 安装配置页面。此项目需求 PaddlePaddle 2.2.0+。
### 安装 Paddle Quantum
### 安装 Paddle Quantum
我们推荐通过 `pip` 完成安装,
......@@ -91,15 +91,9 @@ pip install -e .
### 量子化学模块的环境设置
我们的量子化学模块是基于 `Openfermion``Psi4` 进行开发的,所以在运行量子化学模块之前需要先行安装这两个 Python 包。
我们的量子化学模块是基于 `Psi4` 进行开发的,所以在运行量子化学模块之前需要先行安装该 Python 包。
> 推荐在 Python3.8 环境中安装这些 Python包。
`Openfermion` 可以用如下指令进行安装。
```bash
pip install openfermion
```
> 推荐在 Python3.8 环境中安装。
在安装 `psi4` 时,我们建议您使用 conda。对于 **MacOS/Linux** 的用户,可以使用如下指令。
......@@ -136,11 +130,14 @@ python main.py
这里,我们提供了一份[**入门手册**](./introduction)方便用户快速上手 Paddle Quantum。目前支持网页阅览和运行 Jupyter Notebook 两种方式。内容上,该手册包括以下几个方面:
- Paddle Quantum 的详细安装教程
- 量子计算的基础知识介绍
- Paddle Quantum 的使用介绍
- PaddlePaddle 飞桨优化器使用教程
- 具体的量子机器学习案例—VQE
- 量桨(Paddle Quantum)的详细安装教程
- 量子计算和量子神经网络的基础知识介绍
- 变分量子算法的基本思想与算法框架
- 量桨的使用介绍
- 飞桨(PaddlePaddle)优化器的使用教程
- 量桨中量子化学模块的使用介绍
- 如何基于 GPU 训练量子神经网络
- 量桨中初学者常用的函数
### 案例入门
......@@ -158,6 +155,7 @@ Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为
7. [基于经典影子的量子态性质估计](./tutorial/quantum_simulation/ClassicalShadow_Application_CN.ipynb)
8. [利用 Product Formula 模拟时间演化](./tutorial/quantum_simulation/HamiltonianSimulation_CN.ipynb)
9. [模拟一维海森堡链的自旋动力学](./tutorial/quantum_simulation/SimulateHeisenberg_CN.ipynb)
10. [基于施密特分解的分布式变分量子本征求解器](./tutorial/quantum_simulation/DistributedVQE_CN.ipynb)
- [机器学习](./tutorial/machine_learning)
1. [量子态编码经典数据](./tutorial/machine_learning/DataEncoding_CN.ipynb)
......@@ -191,6 +189,7 @@ Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为
3. [使用量子电路计算梯度](./tutorial/qnn_research/Gradient_CN.ipynb)
4. [量子神经网络的表达能力](./tutorial/qnn_research/Expressibility_CN.ipynb)
5. [变分量子电路编译](./tutorial/qnn_research/VQCC_CN.ipynb)
6. [量子费舍信息](./tutorial/qnn_research/Fisher_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)
......@@ -202,7 +201,7 @@ Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为
### 开发
Paddle Quantum 使用 setuptools 的 develop 模式进行安装,相关代码修改可以直接进入`paddle_quantum` 文件夹进行修改。python 文件携带了自说明注释。
Paddle Quantum 使用 setuptools 的 develop 模式进行安装,相关代码修改可以直接进入 `paddle_quantum` 文件夹进行修改。python 文件携带了自说明注释。
## 交流与反馈
......@@ -212,7 +211,7 @@ Paddle Quantum 使用 setuptools 的 develop 模式进行安装,相关代码
## 使用 Paddle Quantum 的工作
我们非常欢迎开发者使用 Paddle Quantum 进行量子机器学习的研发,如果您的工作有使用 Paddle Quantum,也非常欢迎联系我们。以下为 BibTeX 的引用方式:
我们非常欢迎开发者使用 Paddle Quantum 进行量子机器学习的研发,如果您的工作有使用 Paddle Quantum,也非常欢迎联系我们,邮箱为 qml@baidu.com。以下为 BibTeX 的引用方式:
> @misc{Paddlequantum,
> title = {{Paddle Quantum}},
......@@ -221,17 +220,17 @@ Paddle Quantum 使用 setuptools 的 develop 模式进行安装,相关代码
目前使用 Paddle Quantum 的代表性工作包括了吉布斯态的制备和变分量子奇异值分解:
[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)]
[1] Wang, Youle, Guangxi Li, and Xin Wang. "Variational quantum Gibbs state preparation with a truncated Taylor series." Physical Review Applied 16.5 (2021): 054035. [[pdf](https://arxiv.org/pdf/2005.08797.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)]
[2] Wang, Xin, Zhixin Song, and Youle Wang. "Variational quantum singular value decomposition." Quantum 5 (2021): 483. [[pdf](https://arxiv.org/pdf/2006.02336.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.
[3] Li, Guangxi, Zhixin Song, and Xin Wang. "VSQL: Variational Shadow Quantum Learning for Classification." Proceedings of the AAAI Conference on Artificial Intelligence. Vol. 35. No. 9. 2021. [[pdf]](https://arxiv.org/pdf/2012.08288.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)
[4] Chen, Ranyiliu, et al. "Variational quantum algorithms for trace distance and fidelity estimation." Quantum Science and Technology (2021). [[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)
[6] Zhao, Xuanqiang, et al. "Practical distributed quantum information processing with LOCCNet." npj Quantum Information 7.1 (2021): 1-7. [[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)
......
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import Hamiltonian,NKron, gate_fidelity,SpinOps,dagger
from paddle_quantum.trotter import construct_trotter_circuit, get_1d_heisenberg_hamiltonian
from paddle import matmul, transpose, trace
import paddle
import numpy as np
import scipy
from scipy import linalg
import matplotlib.pyplot as plt
def get_evolve_op(t,h): return scipy.linalg.expm(-1j * t * h.construct_h_matrix())
def test(h,n):
t = 2
r = 1
cir = UAnsatz(n)
construct_trotter_circuit(cir, h, tau=t/r, steps=r)
print('系统的哈密顿量为:')
print(h)
print('电路的酉矩阵与正确的演化算符之间的保真度为:%.2f' % gate_fidelity(cir.U.numpy(), get_evolve_op(t,h)))
print(cir)
print('--------------test1------------')
h1 = get_1d_heisenberg_hamiltonian(length=2, j_x=1, j_y=1, j_z=2,h_z=2 * np.random.rand(2) - 1,periodic_boundary_condition=False)#
test(h1,2)
print('--------------test2------------')
h2 = Hamiltonian([[1., 'X0, X1'], [1., 'Z2, Z3'], [1., 'Y0, Y1'], [1., 'X1, X2'], [1., 'Y2, Y3'], [1., 'Z0, Z1']])
test(h2,4)
print('--------------test3------------')
h3 = Hamiltonian([ [1, 'Y0, Y1'], [1, 'X1, X0'],[1, 'X0, Y1'],[1, 'Z0, Z1']])
test(h3,2)
"""
运行耗时: 130毫秒
--------------test1------------
([1.0, 1.0, 2.0, 0.8812020131972615, 0.7453483155128535], ['XX', 'YY', 'ZZ', 'Z', 'Z'], [[0, 1], [0, 1], [0, 1], [0], [1]])
系统的哈密顿量为:
1.0 X0, X1
1.0 Y0, Y1
2.0 Z0, Z1
0.8812020131972615 Z0
0.7453483155128535 Z1
电路的酉矩阵与正确的演化算符之间的保真度为:0.99
---------------x----Rz(6.429)----*-----------------x----Rz(-1.57)----Rz(3.525)--
| | |
--Rz(1.571)----*----Ry(-3.85)----x----Ry(3.854)----*----Rz(2.981)---------------
--------------test2------------
([1.0, 1.0, 1.0, 1.0, 1.0, 1.0], ['XX', 'YY', 'ZZ', 'ZZ', 'XX', 'YY'], [[0, 1], [0, 1], [0, 1], [2, 3], [1, 2], [2, 3]])
系统的哈密顿量为:
1.0 X0, X1
1.0 Z2, Z3
1.0 Y0, Y1
1.0 X1, X2
1.0 Y2, Y3
1.0 Z0, Z1
电路的酉矩阵与正确的演化算符之间的保真度为:0.51
-------------------x--------Rz(2.429)--------*---------------------x----Rz(-1.57)-------------------------------------------------------------------------------
| | |
--Rz(1.571)--------*--------Ry(-3.85)--------x--------Ry(3.854)----*--------H--------*-----------------*----H---------------------------------------------------
| |
------*-------------------------*------------H---------------------------------------x----Rz(4.000)----x----H----Rx(1.571)----*-----------------*----Rx(-1.57)--
| | | |
------x--------Rz(4.000)--------x--------Rx(1.571)----------------------------------------------------------------------------x----Rz(4.000)----x----Rx(-1.57)--
--------------test3------------
([1.0, 1.0, 1.0, 1.0], ['YY', 'XX', 'ZZ', 'XY'], [[0, 1], [1, 0], [0, 1], [0, 1]])
系统的哈密顿量为:
1.0 Y0, Y1
1.0 X1, X0
1.0 X0, Y1
1.0 Z0, Z1
电路的酉矩阵与正确的演化算符之间的保真度为:0.46
---------------x----Rz(2.429)----*-----------------x----Rz(-1.57)----H----*-----------------*--------H------
| | | | |
--Rz(1.571)----*----Ry(-3.85)----x----Ry(3.854)----*----Rx(1.571)---------x----Rz(4.000)----x----Rx(-1.57)--
"""
from paddle_quantum.utils import partial_trace,plot_state_in_bloch_sphere,partial_trace_discontiguous,NKron,plot_n_qubit_state_in_bloch_sphere
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import paddle
cir1 = UAnsatz(1)
cir2 = UAnsatz(1)
phi, theta, omega = 2 * np.pi * np.random.uniform(size=3)
phi = paddle.to_tensor(phi, dtype='float64')
theta = paddle.to_tensor(theta, dtype='float64')
omega = paddle.to_tensor(omega, dtype='float64')
cir1.rx(phi,0)
cir1.rz(omega,0)
cir2.ry(theta,0)
mat1,mat2 = np.array(cir1.run_density_matrix()),np.array(cir2.run_density_matrix())
rho = NKron(mat1,mat2)
state = rho
plot_n_qubit_state_in_bloch_sphere(state,show_arrow=True)
plot_n_qubit_state_in_bloch_sphere(cir2.run_density_matrix(),show_arrow=True)
plot_n_qubit_state_in_bloch_sphere(cir1.run_state_vector(),show_arrow=True)
此差异已折叠。
此差异已折叠。
......@@ -137,7 +137,11 @@
"source": [
"我们可以在命令行中输入`nvidia-smi`来查看 GPU 的使用情况,包括有哪些程序在哪些 GPU 上运行,以及其显存占用情况。\n",
"\n",
"这里,我们以 [VQE](../tutorial/quantum_simulation/VQE_CN.ipynb) 为例来说明我们该如何使用 GPU。首先,导入相关的包并定义相关的变量和函数。"
"这里我们以变分量子本征求解器(Variational Quantum Eigensolver, [VQE](/tutorials/quantum-simulation/variational-quantum-eigensolver.html) )为例来说明我们该如何使用GPU。简单来说,它利用参数化的电路搜寻广阔的希尔伯特空间,并利用经典机器学习中的梯度下降来找到最优参数,并接近一个哈密顿量(Hamiltonian)的基态(也就是找到一个埃尔米特矩阵的最小本征值)。此处哈密顿量由以下 H2_generator() 函数给出,使用的量子神经网络架构如下图所示:\n",
"\n",
"![circuit](./figures/gpu-fig-circuit.jpg)\n",
"\n",
"首先,导入相关的包并定义相关的变量和函数:"
]
},
{
......@@ -398,7 +402,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
......
......@@ -142,7 +142,12 @@
"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](../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."
"Here, we take Variational Quantum Eigensolver ([VQE](/tutorials/quantum-simulation/variational-quantum-eigensolver.html)) as an example to illustrate how we should use GPU. \n",
"For simplicity, VQA use a parameterized quantum circuit to search the vast Hilbert space, and uses the gradient descent method to find the optimal parameters, to get close to the ground state of a Hamiltonian (the smallest eigenvalue of the Hermitian matrix). The Hamiltonian in our example is given by the following H2_generator() function, and the quantum neural network has the following structure:\n",
"\n",
"![circuit](./figures/gpu-fig-circuit.jpg)\n",
"\n",
"First, import the related packages and define some variables and functions:"
]
},
{
......@@ -405,7 +410,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
"version": "3.7.10"
},
"toc": {
"base_numbering": 1,
......
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 利用 Paddle Quantum 的 qchem 模块进行量子化学计算\n",
"_Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved._\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"qchem 是基于 Paddle Quantum 推出的用于量子化学研究的工具集。qchem 为量子化学领域的研究者提供了一系列工具,使他们可以利用量子计算方法完成量子化学任务。与此同时,qchem 也提供了方便开发者进行功能拓展的方式。目前,qchem 正处于开发之中,您可以将需求和建议通过 Github 的 issue 或 pull request 反馈给我们,我们会及时给出回复。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 分子基态能量计算\n",
"qchem 提供了 `run_chem` 函数来计算给定分子的基态能量和基态波函数。让我们通过计算氢分子基态能量的例子来了解一下整个计算过程。首先,让我们导入需要用的函数。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from paddle_quantum import qchem"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"接下来,让我们把与计算相关的信息输入到 `run_chem` 函数中,这些信息包括:分子的几何结构、分子的电荷、计算需要用到的量子化学基函数等。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# define the geometry of hydrogen molecule, length unit use angstrom.\n",
"h2_geometry = [(\"H\", [0.0, 0.0, 0.0]), (\"H\", [0.0, 0.0, 0.74])]\n",
"charge = 0\n",
"basis_set = \"sto-3g\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"现在,我们需要选择一种多体波函数的量子线路模版来作为基态能量计算中的变分波函数。目前,qchem 提供了两种模式,分别是 \"hardware efficient\" [<sup>1</sup>](#refer-1) 和 \"hartree fock\" [<sup>2</sup>](#refer-2) ,更多的模式正在开发中,很快也会上线。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# call run_chem function with \"hardware efficient\" ansatz.\n",
"h2_gs_en, h2_wf_model = qchem.run_chem(\n",
" h2_geometry,\n",
" \"hardware efficient\",\n",
" basis_set, \n",
" charge\n",
")\n",
"\n",
"# additional information for optimizer can be passed using `optimizer_option` keyword argument.\n",
"h2_gs_en, h2_wf_model = qchem.run_chem(\n",
" h2_geometry,\n",
" \"hardware efficient\",\n",
" basis_set, \n",
" charge,\n",
" optimizer_option={\"learning_rate\": 0.6, \"weight_decay\": 0.9}\n",
")\n",
"\n",
"# additional information for ansatz can be passed using `ansatz_option` keyword argument, e.g.\n",
"# \"hardware efficient\" ansatz has a parameter \"cir_depth\", which can be used to specify the depth\n",
"# of quantum circuit.\n",
"h2_gs_en, h2_wf_model = qchem.run_chem(\n",
" h2_geometry,\n",
" \"hardware efficient\",\n",
" basis_set, \n",
" charge,\n",
" ansatz_option={\"cir_depth\": 5}\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"除了上面这些参数,我们也可以通过给定 `max_iters` 和 `a_tol` 来控制训练过程的迭代次数和收敛条件。如果想使用 \"hartree fock\" 量子线路,我们只需要把上面代码中的 \"hardware efficient\" 替换为 \"hartree fock\" 就可以了。我们也可以通过 `print(h2_wf_model.circuit)` 的方法来查看氢分子波函数的量子线路。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 自定义量子线路\n",
"在 qchem 中,我们也为感兴趣的使用者提供了自定义量子线路的方法。我们只需要继承 qchem 中的 Qmodel 类就可以像在 paddlepaddle 中定义神经网络一样定义波函数对应的量子线路。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum import qchem\n",
"from paddle_quantum.qchem.layers import CrossResonanceLayer, EulerRotationLayer\n",
"\n",
"\n",
"# Your own model should inherit from `Qmodel`.\n",
"## NOTE: THIS MODEL IS ONLY DEFINED FOR DEMONSTRATION PURPOSE! \n",
"class MyAnsatz(qchem.QModel):\n",
" def __init__(self, n_qubits):\n",
" super().__init__(n_qubits)\n",
"\n",
" self.entangle = CrossResonanceLayer(self._n_qubit)\n",
" self.rot = EulerRotationLayer(self._n_qubit)\n",
"\n",
" def forward(self, state):\n",
" self._circuit = UAnsatz(self.n_qubit)\n",
"\n",
" out = self.entangle(state)\n",
" self._circuit += self.entangle.circuit\n",
"\n",
" out = self.rot(out)\n",
" self._circuit += self.rot.circuit\n",
"\n",
" out = self.entangle(out)\n",
" self._circuit += self.entangle.circuit\n",
"\n",
" return out\n",
"\n",
"# instantiate your model\n",
"my_cir = MyAnsatz(5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"在定义好线路之后,我们就可以利用 paddlepaddle 提供的多种优化器来优化线路中的参数以获得最佳结果。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# use paddlepaddle's optimizer\n",
"import numpy as np \n",
"import paddle\n",
"\n",
"optimizer = paddle.optimizer.Adam(parameters=my_cir.parameters(), learning_rate=0.08)\n",
"\n",
"# define the loss function\n",
"## NOTE: THIS LOSS FUNCTION IS ONLY DEFINED FOR DEMONSTRATION PURPOSE!\n",
"def loss_fn(state: paddle.Tensor) -> paddle.Tensor:\n",
" return paddle.norm(state.real())\n",
"\n",
"# start learning\n",
"s0 = np.zeros((2**5,), dtype=np.complex128)\n",
"s0[0] = 1.0+0.0j\n",
"s0 = paddle.to_tensor(s0)\n",
"\n",
"for i in range(10):\n",
" loss = loss_fn(my_cir(s0))\n",
" print(f\"At {i:>d}th step: loss={loss.item():>.5f}.\")\n",
"\n",
" optimizer.clear_grad()\n",
" loss.backward()\n",
" optimizer.step()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"## 参考文献\n",
"\n",
"[1] Kandala, Abhinav, et al. \"Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets.\" [Nature 549.7671 (2017): 242-246.](https://www.nature.com/articles/nature23879)\n",
"\n",
"[2] Arute, Frank, et al. \"Hartree-Fock on a superconducting qubit quantum computer.\" [Science 369.6507 (2020): 1084-1089.](https://www.science.org/doi/10.1126/science.abb9811)"
]
}
],
"metadata": {
"interpreter": {
"hash": "385f93486cadd2f2140b6b583192a2daa18c8b591e699592075836b347373dd4"
},
"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"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Quantum Chemistry with Paddle Quantum's qchem\n",
"*Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"qchem, which builds on top of Paddle Quantum, is designed to be a toolkit for quantum chemistry research in quantum computing era. It provides high level APIs for researchers who are interested in leveraging their current quantum chemsitry calculation with quantum computing power. And it also allows experts to write customized code. qchem is currently under active development, feel free to join us by opening issues or pull requests."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Calculate ground state energy of a molecule\n",
"qchem provides `run_chem` function to calculate the ground state energy and ground state wave function. For example, let's try to calculate the ground state energy of hydrogen molecule. First, we need to import qchem."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from paddle_quantum import qchem"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then, we need to provide chemical information required by `run_chem` function, including geometry, charge, basis function etc."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# define the geometry of hydrogen molecule, length unit use angstrom.\n",
"h2_geometry = [(\"H\", [0.0, 0.0, 0.0]), (\"H\", [0.0, 0.0, 0.74])]\n",
"charge = 0\n",
"basis_set = \"sto-3g\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, let's choose an ansatz of many-electron wave function for our ground state energy calculation. Currently, you can choose to use \"hardware efficient\" [<sup>1</sup>](#refer-1) or \"hartree fock\" [<sup>2</sup>](#refer-2) ansatz, more functionalities will be released in the future. Let's choose \"hardware efficient\" ansatz."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# call run_chem function with \"hardware efficient\" ansatz.\n",
"h2_gs_en, h2_wf_model = qchem.run_chem(\n",
" h2_geometry,\n",
" \"hardware efficient\",\n",
" basis_set, \n",
" charge\n",
")\n",
"\n",
"# additional information for optimizer can be passed using `optimizer_option` keyword argument.\n",
"h2_gs_en, h2_wf_model = qchem.run_chem(\n",
" h2_geometry,\n",
" \"hardware efficient\",\n",
" basis_set, \n",
" charge,\n",
" optimizer_option={\"learning_rate\": 0.6, \"weight_decay\": 0.9}\n",
")\n",
"\n",
"# additional information for ansatz can be passed using `ansatz_option` keyword argument, e.g.\n",
"# \"hardware efficient\" ansatz has a parameter \"cir_depth\", which can be used to specify the depth\n",
"# of quantum circuit.\n",
"h2_gs_en, h2_wf_model = qchem.run_chem(\n",
" h2_geometry,\n",
" \"hardware efficient\",\n",
" basis_set, \n",
" charge,\n",
" ansatz_option={\"cir_depth\": 5}\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also specify `max_iters` and `a_tol` keyword arguments to control the maximum iteration cycles and convergence criteria of the optimization process. \n",
"\n",
"To try another ansatz, you just need to replace the ansatz argument to, e.g. \"hartree fock\", and run similar command.\n",
"\n",
"To see the quantum circuit for hydrogen molecule's hardware efficient ansatz, you can run `print(h2_wf_model.circuit)`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Design your own ansatz\n",
"For those who want to try an ansatz that isn't currently included in qchem, we provide method to write your own ansatz. Writing your own ansatz is similar to defining an neural network in paddlepaddle, except that your ansatz should inherit from `Qmodel`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from paddle_quantum.circuit import UAnsatz\n",
"from paddle_quantum import qchem\n",
"from paddle_quantum.qchem.layers import CrossResonanceLayer, EulerRotationLayer\n",
"\n",
"\n",
"# Your own model should inherit from `Qmodel`.\n",
"## NOTE: THIS MODEL IS ONLY DEFINED FOR DEMONSTRATION PURPOSE! \n",
"class MyAnsatz(qchem.QModel):\n",
" def __init__(self, n_qubits):\n",
" super().__init__(n_qubits)\n",
"\n",
" self.entangle = CrossResonanceLayer(self._n_qubit)\n",
" self.rot = EulerRotationLayer(self._n_qubit)\n",
"\n",
" def forward(self, state):\n",
" self._circuit = UAnsatz(self.n_qubit)\n",
"\n",
" out = self.entangle(state)\n",
" self._circuit += self.entangle.circuit\n",
"\n",
" out = self.rot(out)\n",
" self._circuit += self.rot.circuit\n",
"\n",
" out = self.entangle(out)\n",
" self._circuit += self.entangle.circuit\n",
"\n",
" return out\n",
"\n",
"# instantiate your model\n",
"my_cir = MyAnsatz(5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can then follow the optimization procedure [here](https://qml.baidu.com/tutorials/quantum-simulation/variational-quantum-eigensolver.html) and use any paddlepaddle optimizer to train the ansatz you have built."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# use paddlepaddle's optimizer\n",
"import numpy as np \n",
"import paddle\n",
"\n",
"optimizer = paddle.optimizer.Adam(parameters=my_cir.parameters(), learning_rate=0.08)\n",
"\n",
"# define the loss function\n",
"## NOTE: THIS LOSS FUNCTION IS ONLY DEFINED FOR DEMONSTRATION PURPOSE!\n",
"def loss_fn(state: paddle.Tensor) -> paddle.Tensor:\n",
" return paddle.norm(state.real())\n",
"\n",
"# start learning\n",
"s0 = np.zeros((2**5,), dtype=np.complex128)\n",
"s0[0] = 1.0+0.0j\n",
"s0 = paddle.to_tensor(s0)\n",
"\n",
"for i in range(10):\n",
" loss = loss_fn(my_cir(s0))\n",
" print(f\"At {i:>d}th step: loss={loss.item():>.5f}.\")\n",
"\n",
" optimizer.clear_grad()\n",
" loss.backward()\n",
" optimizer.step()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"## References\n",
"\n",
"[1] Kandala, Abhinav, et al. \"Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets.\" [Nature 549.7671 (2017): 242-246.](https://www.nature.com/articles/nature23879)\n",
"\n",
"[2] Arute, Frank, et al. \"Hartree-Fock on a superconducting qubit quantum computer.\" [Science 369.6507 (2020): 1084-1089.](https://www.science.org/doi/10.1126/science.abb9811)"
]
}
],
"metadata": {
"interpreter": {
"hash": "7b343e878babc25549085ff27e754b596ec1b81bbbd70d50b28da4f6023d5bd9"
},
"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"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
......@@ -17,4 +17,4 @@ Paddle Quantum Library
"""
name = "paddle_quantum"
__version__ = "2.1.2"
__version__ = "2.1.3"
......@@ -26,7 +26,7 @@ from paddle import imag, real, reshape, kron, matmul, trace
from paddle_quantum.utils import partial_trace, dagger, pauli_str_to_matrix
from paddle_quantum import shadow
from paddle_quantum.intrinsic import *
from paddle_quantum.state import density_op,vec
from paddle_quantum.state import density_op, vec
__all__ = [
"UAnsatz",
......@@ -60,38 +60,15 @@ class UAnsatz:
# Record history of adding gates to the circuit
self.__history = []
def expand(self,new_n):
"""
为原来的量子电路进行比特数扩展
Args:
new_n(int):扩展后的量子比特数
"""
assert new_n>=self.n,'扩展后量子比特数要大于原量子比特数'
diff = new_n-self.n
dim = 2**diff
if self.__state is not None:
if self.__run_mode=='density_matrix':
shape = (dim,dim)
_state = paddle.to_tensor(density_op(diff))
elif self.__run_mode=='state_vector':
shape = (dim,)
_state = paddle.to_tensor(vec(0,diff))
_state= paddle.reshape(_state,shape)
_state = kron(self.__state,_state)
self.__state = _state
self.n = new_n
def __add__(self, cir):
r"""重载加法 ‘+’ 运算符,用于拼接两个维度相同的电路
Args:
cir (UAnsatz): 拼接到现有电路上的电路
Returns:
UAnsatz: 拼接后的新电路
代码示例:
.. code-block:: python
......@@ -113,19 +90,19 @@ class UAnsatz:
print(cir3)
::
cir1:
cir1:
--H--
--H--
cir2:
cir2:
--*--
|
|
--x--
cir3:
cir3:
--H----*--
|
|
--H----x--
"""
......@@ -304,13 +281,13 @@ class UAnsatz:
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()
......@@ -419,6 +396,29 @@ class UAnsatz:
return return_str
def expand(self, qubit_num):
"""
为原来的量子电路进行比特数扩展
Args:
qubit_num (int): 扩展后的量子比特数
"""
assert qubit_num >= self.n, '扩展后量子比特数要大于原量子比特数'
diff = qubit_num - self.n
dim = 2 ** diff
if self.__state is not None:
if self.__run_mode == 'density_matrix':
shape = (dim, dim)
_state = paddle.to_tensor(density_op(diff))
elif self.__run_mode == 'state_vector':
shape = (dim,)
_state = paddle.to_tensor(vec(0, diff))
_state = paddle.reshape(_state, shape)
_state = kron(self.__state, _state)
self.__state = _state
self.n = qubit_num
def run_state_vector(self, input_state=None, store_state=True):
r"""运行当前的量子电路,输入输出的形式为态矢量。
......@@ -1160,7 +1160,7 @@ class UAnsatz:
.. math::
\begin{align}
CNOT &=|0\rangle \langle 0|\otimes I + |1 \rangle \langle 1|\otimes X\\
CY &=|0\rangle \langle 0|\otimes I + |1 \rangle \langle 1|\otimes Y\\
&=
\begin{bmatrix}
1 & 0 & 0 & 0 \\
......@@ -1197,7 +1197,7 @@ class UAnsatz:
.. math::
\begin{align}
CNOT &=|0\rangle \langle 0|\otimes I + |1 \rangle \langle 1|\otimes X\\
CZ &=|0\rangle \langle 0|\otimes I + |1 \rangle \langle 1|\otimes Z\\
&=
\begin{bmatrix}
1 & 0 & 0 & 0 \\
......@@ -1915,9 +1915,9 @@ class UAnsatz:
::
------------x----Rx(3.142)----Ryy(1.57)---------------
| |
| |
------------|-----------------Ryy(1.57)----Rz(0.785)--
|
|
--H---SDG---*--------H--------------------------------
"""
history, param = self._get_history()
......@@ -1975,15 +1975,15 @@ class UAnsatz:
::
--Rx(3.142)----Ryy(1.57)-------------*------
| |
| |
---------------Ryy(1.57)----z----Rz(0.785)--
|
|
------H-----------SDG-------*--------H------
--Rx(3.142)----Ryy(1.57)----z-------------*------
| | |
| | |
---------------Ryy(1.57)----|----z----Rz(0.785)--
| |
| |
------H------------S--------*----*--------H------
"""
history, param = self._get_history()
......@@ -2035,9 +2035,9 @@ class UAnsatz:
::
------------z----U--
|
|
------------|-------
|
|
--H---SDG---*----H--
"""
history, param = self._get_history()
......@@ -2101,15 +2101,15 @@ class UAnsatz:
::
-----------------x--
|
|
------------z----U--
|
|
--H---SDG---*----H--
------------z---------x--
| |
| |
------------|----z----U--
| |
| |
--H----S----*----*----H--
"""
history, param = self._get_history()
......@@ -3098,7 +3098,7 @@ class UAnsatz:
def update_param(self, new_param):
r"""用得到的新参数列表更新电路参数列表中的可训练的参数。
Args:
new_param (list): 新的参数列表
......@@ -3108,8 +3108,11 @@ class UAnsatz:
j = 0
for i in range(len(self.__param)):
if not self.__param[i].stop_gradient:
self.__param[i] = paddle.to_tensor(new_param[j], 'float64')
self.__param[i].stop_gradient = False
if not isinstance(new_param[j], paddle.Tensor):
self.__param[i] = paddle.to_tensor(new_param[j], 'float64')
self.__param[i].stop_gradient = False
else:
self.__param[i] = new_param[j]
j += 1
self.run_state_vector()
return self.__param
......
此差异已折叠。
# 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.
"""
梯度分析工具模块
"""
import numpy as np
import paddle
from paddle import reshape
from random import choice
from tqdm import tqdm
import matplotlib.pyplot as plt
__all__ = [
"StateNet",
"show_gradient",
"random_sample",
"random_sample_supervised",
"plot_loss_grad",
"plot_supervised_loss_grad",
"plot_distribution"
]
class StateNet(paddle.nn.Layer):
r"""定义用于量子机器学习的量子神经网络模型
用户可以通过实例化该类定义自己的量子神经网络模型。
"""
def __init__(self, shape, dtype='float64'):
r"""构造函数,用于实例化一个 ``StateNet`` 对象
Args:
shape (paddle.Tensor): 表示传入的量子电路中的需要被优化的参数个数
"""
super(StateNet, self).__init__()
self.theta = self.create_parameter(shape=shape,
default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*np.pi),
dtype=dtype, is_bias=False)
def forward(self, circuit, loss_func, *args):
r"""用于更新电路参数并计算该量子神经网络的损失值。
Args:
circuit (UAnsatz): 表示传入的参数化量子电路,即要训练的量子神经网络
loss_func (function): 表示计算该量子神经网络损失值的函数
*args (list): 表示用于损失函数计算的额外参数列表
Note:
这里的 ``loss_func`` 是一个用户自定义的计算损失值的函数,参数为电路和一个可变参数列表。
Returns:
tuple: 包含如下两个元素:
- loss (paddle.Tensor): 表示该量子神经网络损失值
- circuit (UAnsatz): 更新参数后的量子电路
"""
circuit.update_param(self.theta)
circuit.run_state_vector()
loss = loss_func(circuit, *args)
return loss, circuit
def show_gradient(circuit, loss_func, ITR, LR, *args):
r"""计算量子神经网络中各可变参数的梯度值和损失函数值
Args:
circuit (UAnsatz): 表示传入的参数化量子电路,即要训练的量子神经网络
loss_func (function): 表示计算该量子神经网络损失值的函数
ITR (int): 表示训练的次数
LR (float): 表示学习训练的速率
*args (list): 表示用于损失函数计算的额外参数列表
Returns:
tuple: 包含如下两个元素:
- loss_list (list): 表示损失函数值随训练次数变化的列表
- grad_list(list): 表示各参数梯度随训练次变化的列表
"""
grad_list = []
loss_list = []
shape = paddle.shape(circuit.get_param())
net = StateNet(shape=shape)
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
pbar = tqdm(
desc="Training: ", total=ITR, ncols=100, ascii=True
)
for itr in range(ITR):
pbar.update(1)
loss, cir = net(circuit, loss_func, *args)
loss.backward()
grad = net.theta.grad.numpy()
grad_list.append(grad)
loss_list.append(loss.numpy()[0])
opt.minimize(loss)
opt.clear_grad()
pbar.close()
return loss_list, grad_list
def plot_distribution(grad):
r"""根据输入的梯度的列表,画出梯度的分布图
Args:
grad (np.array): 表示量子神经网络某参数的梯度列表
"""
grad = np.abs(grad)
grad_list = [0, 0, 0, 0, 0]
x = ['<0.0001', ' (0.0001,0.001)', '(0.001,0.01)', '(0.01,0.1)', '>0.1']
for g in grad:
if g > 0.1:
grad_list[4] += 1
elif g > 0.01:
grad_list[3] += 1
elif g > 0.001:
grad_list[2] += 1
elif g > 0.0001:
grad_list[1] += 1
else:
grad_list[0] += 1
grad_list = np.array(grad_list) / len(grad)
plt.figure()
plt.bar(x, grad_list, width=0.5)
plt.title('The gradient distribution of variables')
plt.ylabel('ratio')
plt.show()
def random_sample(circuit, loss_func, sample_num, *args, mode='single', if_plot=True, param=0):
r"""表示对模型进行随机采样,根据不同的计算模式,获得对应的平均值和方差
Args:
circuit (UAnsatz): 表示传入的参数化量子电路,即要训练的量子神经网络
loss_func (function): 表示计算该量子神经网络损失值的函数
sample_num (int): 表示随机采样的次数
mode (string): 表示随机采样后的计算模式,默认为 'single'
if_plot(boolean): 表示是否对梯度进行画图表示
param (int): 表示 ``Single`` 模式中对第几个参数进行画图,默认为第一个参数
*args (list): 表示用于损失函数计算的额外参数列表
Note:
在本函数中提供了三种计算模式,``mode`` 分别可以选择 ``'single'``, ``'max'``, 以及 ``'random'``
- mode='single': 表示计算电路中的每个可变参数梯度的平均值和方差
- mode='max': 表示对电路中每轮采样的所有参数梯度的最大值求平均值和方差
- mode='random': 表示对电路中每轮采样的所有参数随机取一个梯度,求平均值和方差
Returns:
tuple: 包含如下两个元素:
- loss_list (list): 表示多次采样后损失函数值的列表
- grad_list(list): 表示多次采样后各参数梯度的列表
"""
loss_list, grad_list = [], []
pbar = tqdm(
desc="Sampling: ", total=sample_num, ncols=100, ascii=True
)
for itr in range(sample_num):
pbar.update(1)
shape = paddle.shape(circuit.get_param())
net = StateNet(shape=shape)
loss, cir = net(circuit, loss_func, *args)
loss.backward()
grad = net.theta.grad.numpy()
loss_list.append(loss.numpy()[0])
grad_list.append(grad)
pbar.close()
if mode == 'single':
grad_list = np.array(grad_list)
grad_list = grad_list.transpose()
grad_variance_list = []
grad_mean_list = []
for idx in range(len(grad_list)):
grad_variance_list.append(np.var(grad_list[idx]))
grad_mean_list.append(np.mean(grad_list[idx]))
print("Mean of gradient for all parameters: ")
for i in range(len(grad_mean_list)):
print("theta", i+1, ": ", grad_mean_list[i])
print("Variance of gradient for all parameters: ")
for i in range(len(grad_variance_list)):
print("theta", i+1, ": ", grad_variance_list[i])
if if_plot:
plot_distribution(grad_list[param])
return grad_mean_list, grad_variance_list
if mode == 'max':
max_grad_list = []
for idx in range(len(grad_list)):
max_grad_list.append(np.max(np.abs(grad_list[idx])))
print("Mean of max gradient")
print(np.mean(max_grad_list))
print("Variance of max gradient")
print(np.var(max_grad_list))
if if_plot:
plot_distribution(max_grad_list)
return np.mean(max_grad_list), np.var(max_grad_list)
if mode == 'random':
random_grad_list = []
for idx in range(len(grad_list)):
random_grad = choice(grad_list[idx])
random_grad_list.append(random_grad)
print("Mean of random gradient")
print(np.mean(random_grad_list))
print("Variance of random gradient")
print(np.var(random_grad_list))
if if_plot:
plot_distribution(random_grad_list)
return np.mean(random_grad_list), np.var(random_grad_list)
return loss_list, grad_list
def plot_loss_grad(circuit, loss_func, ITR, LR, *args):
r"""绘制损失值和梯度随训练次数变化的图
Args:
circuit (UAnsatz): 表示传入的参数化量子电路,即要训练的量子神经网络
loss_func (function): 表示计算该量子神经网络损失值的函数
ITR (int): 表示训练的次数
LR (float): 表示学习训练的速率
*args (list): 表示用于损失函数计算的额外参数列表
"""
loss, grad = show_gradient(circuit, loss_func, ITR, LR, *args)
plt.xlabel(r"Iteration")
plt.ylabel(r"Loss")
plt.plot(range(1, ITR+1), loss, 'r', label='loss')
plt.legend()
plt.show()
max_grad = [np.max(np.abs(i)) for i in grad]
plt.xlabel(r"Iteration")
plt.ylabel(r"Gradient")
plt.plot(range(1, ITR+1), max_grad, 'b', label='gradient')
plt.legend()
plt.show()
def plot_supervised_loss_grad(circuit, loss_func, N, EPOCH, LR, BATCH, TRAIN_X, TRAIN_Y, *args):
r"""绘制监督学习中损失值和梯度随训练次数变化的图
Args:
circuit (UAnsatz): 表示传入的参数化量子电路,即要训练的量子神经网络
loss_func (function): 表示计算该量子神经网络损失值的函数
N (int): 表示量子比特的数量
EPOCH (int): 表示训练的轮数
LR (float): 表示学习训练的速率
BATCH (int): 表示训练时 batch 的大小
TRAIN_X (paddle.Tensor): 表示训练数据集
TRAIN_Y (list): 表示训练数据集的标签
*args (list): 表示用于损失函数计算的额外参数列表
Returns:
tuple: 包含如下两个元素:
- loss_list (list): 表示多次训练的损失函数值列表
- grad_list(list): 表示多次训练后各参数梯度的列表
"""
grad_list = []
loss_list = []
if type(TRAIN_X) != paddle.Tensor:
raise Exception("Training data should be paddle.Tensor type")
shape = paddle.shape(circuit.get_param())
net = StateNet(shape=shape)
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
for ep in range(EPOCH):
for itr in range(len(TRAIN_X)//BATCH):
input_state = TRAIN_X[itr*BATCH:(itr+1)*BATCH]
input_state = reshape(input_state, [-1, 1, 2**N])
label = TRAIN_Y[itr * BATCH:(itr + 1) * BATCH]
loss, circuit = net(circuit, loss_func, input_state, label)
loss.backward()
grad = net.theta.grad.numpy()
grad_list.append(grad)
loss_list.append(loss.numpy()[0])
opt.minimize(loss)
opt.clear_grad()
max_grad = [np.max(np.abs(i)) for i in grad_list]
plt.xlabel(r"Iteration")
plt.ylabel(r"Loss")
plt.plot(range(1, EPOCH*len(TRAIN_X)//BATCH+1), loss_list, 'r', label='loss')
plt.legend()
plt.show()
plt.xlabel(r"Iteration")
plt.ylabel(r"Gradient")
plt.plot(range(1, EPOCH*len(TRAIN_X)//BATCH+1), max_grad, 'b', label='gradient')
plt.legend()
plt.show()
return loss_list, grad_list
def random_sample_supervised(circuit, loss_func, N, sample_num, BATCH, TRAIN_X, TRAIN_Y, *args, mode='single', if_plot=True, param=0):
r"""表示对监督学习模型进行随机采样,根据不同的计算模式,获得对应的平均值和方差
Args:
circuit (UAnsatz): 表示传入的参数化量子电路,即要训练的量子神经网络
loss_func (function): 表示计算该量子神经网络损失值的函数
N (int): 表示量子比特的数量
sample_num (int): 表示随机采样的次数
BATCH (int): 表示训练时 batch 的大小
TRAIN_X (paddle.Tensor): 表示训练数据集
TRAIN_Y (list): 表示训练数据集的标签
mode (string): 表示随机采样后的计算模式,默认为 'single'
if_plot(boolean): 表示是否对梯度进行画图表示
param (int): 表示 ``Single`` 模式中对第几个参数进行画图,默认为第一个参数
*args (list): 表示用于损失函数计算的额外参数列表
Note:
在本函数中提供了三种计算模式,``mode`` 分别可以选择 ``'single'``, ``'max'``, 以及 ``'random'``
- mode='single': 表示计算电路中的每个可变参数梯度的平均值和方差
- mode='max': 表示对电路中所有参数梯度的最大值求平均值和方差
- mode='random': 表示随机对电路中采样的所有参数随机取一个梯度,求平均值和方差
Returns:
tuple: 包含如下两个元素:
- loss_list (list): 表示多次采样后损失函数值的列表
- grad_list(list): 表示多次采样后各参数梯度的列表
"""
grad_list = []
loss_list = []
input_state = TRAIN_X[0:BATCH]
input_state = reshape(input_state, [-1, 1, 2**N])
label = TRAIN_Y[0: BATCH]
if type(TRAIN_X) != paddle.Tensor:
raise Exception("Training data should be paddle.Tensor type")
label = TRAIN_Y[0: BATCH]
pbar = tqdm(
desc="Sampling: ", total=sample_num, ncols=100, ascii=True
)
for idx in range(sample_num):
pbar.update(1)
shape = paddle.shape(circuit.get_param())
net = StateNet(shape=shape)
loss, circuit = net(circuit, loss_func, input_state, label)
loss.backward()
grad = net.theta.grad.numpy()
grad_list.append(grad)
loss_list.append(loss.numpy()[0])
pbar.close()
if mode == 'single':
grad_list = np.array(grad_list)
grad_list = grad_list.transpose()
grad_variance_list = []
grad_mean_list = []
for idx in range(len(grad_list)):
grad_variance_list.append(np.var(grad_list[idx]))
grad_mean_list.append(np.mean(grad_list[idx]))
print("Mean of gradient for all parameters: ")
for i in range(len(grad_mean_list)):
print("theta", i+1, ": ", grad_mean_list[i])
print("Variance of gradient for all parameters: ")
for i in range(len(grad_variance_list)):
print("theta", i+1, ": ", grad_variance_list[i])
if if_plot:
plot_distribution(grad_list[param])
return grad_mean_list, grad_variance_list
if mode == 'max':
max_grad_list = []
for idx in range(len(grad_list)):
max_grad_list.append(np.max(np.abs(grad_list[idx])))
print("Mean of max gradient")
print(np.mean(max_grad_list))
print("Variance of max gradient")
print(np.var(max_grad_list))
if if_plot:
plot_distribution(max_grad_list)
return np.mean(max_grad_list), np.var(max_grad_list)
if mode == 'random':
random_grad_list = []
for idx in range(len(grad_list)):
random_grad = choice(grad_list[idx])
random_grad_list.append(random_grad)
print("Mean of random gradient")
print(np.mean(random_grad_list))
print("Variance of random gradient")
print(np.var(random_grad_list))
if if_plot:
plot_distribution(random_grad_list)
return np.mean(random_grad_list), np.var(random_grad_list)
return loss_list, grad_list
......@@ -68,7 +68,7 @@ class LoccStatus(object):
return self.measured_result
else:
raise ValueError("too many values to unpack (expected 3)")
def __repr__(self):
return f"state: {self.state.numpy()}\nprob: {self.prob.numpy()[0]}\nmeasured_result: {self.measured_result}"
......
......@@ -967,9 +967,12 @@ def print_progress(current_progress, progress_name, track=True):
assert 0 <= current_progress <= 1, "'current_progress' must be between 0 and 1"
assert isinstance(track, bool), "'track' must be a bool."
if track:
print("\r" + f"{progress_name.ljust(30)}"
f"|{'■' * int(50 * current_progress):{50}s}| "
f"\033[94m {'{:6.2f}'.format(100 * current_progress)}% \033[0m ", flush=True, end="")
print(
"\r"
f"{progress_name.ljust(30)}"
f"|{'■' * int(50 * current_progress):{50}s}| "
f"\033[94m {'{:6.2f}'.format(100 * current_progress)}% \033[0m ", flush=True, end=""
)
if current_progress == 1:
print(" (Done)")
......
......@@ -19,6 +19,7 @@ CG optimizer
from scipy import optimize
from .custom_optimizer import CustomOptimizer
class ConjugateGradient(CustomOptimizer):
r"""ConjugateGradient Optimizer
......@@ -57,6 +58,6 @@ class ConjugateGradient(CustomOptimizer):
method='CG',
jac=self.grad_func,
options={'maxiter': iterations},
callback=lambda xk: print('loss: ', (self.loss_func(xk, self.cir, self.hamiltonian, self.shots)))
)
callback=lambda xk: print('loss: ', self.loss_func(xk, self.cir, self.hamiltonian, self.shots))
)
print(opt_res.message)
......@@ -19,6 +19,7 @@ Newton-CG optimizer
from scipy import optimize
from .custom_optimizer import CustomOptimizer
class NewtonCG(CustomOptimizer):
r"""Newton-CG Optimizer
......@@ -57,6 +58,6 @@ class NewtonCG(CustomOptimizer):
method='Newton-CG',
jac=self.grad_func,
options={'maxiter': iterations},
callback=lambda xk: print('loss: ', (self.loss_func(xk, self.cir, self.hamiltonian, self.shots)))
)
callback=lambda xk: print('loss: ', self.loss_func(xk, self.cir, self.hamiltonian, self.shots))
)
print(opt_res.message)
......@@ -19,6 +19,7 @@ Powell optimizer
from scipy import optimize
from .custom_optimizer import CustomOptimizer
class Powell(CustomOptimizer):
r"""Powell Optimizer
......@@ -54,5 +55,5 @@ class Powell(CustomOptimizer):
method='Powell',
options={'maxiter': iterations},
callback=lambda xk: print('loss: ', self.loss_func(xk, self.cir, self.hamiltonian, self.shots))
)
)
print(opt_res.message)
......@@ -19,6 +19,7 @@ SLSQP optimizer
from scipy import optimize
from .custom_optimizer import CustomOptimizer
class SLSQP(CustomOptimizer):
r"""SLSQP Optimizer
......@@ -53,5 +54,5 @@ class SLSQP(CustomOptimizer):
method='SLSQP',
options={'maxiter': iterations},
callback=lambda xk: print('loss: ', self.loss_func(xk, self.cir, self.hamiltonian, self.shots))
)
)
print(opt_res.message)
# 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.
"""
量桨平台的量子化学模块
"""
from .qmodel import QModel
from . import ansatz
from .run import run_chem
from .qchem import *
import platform
import warnings
__all__ = [
"run_chem",
"QModel",
"ansatz",
"geometry",
"get_molecular_data",
"active_space",
# forward compatible with original qchem module
"fermionic_hamiltonian",
"spin_hamiltonian"
]
if platform.system() == "Windows":
warning_msg = ("Currently, Windows' users can't use 'hartree fock' ansatz "
"for ground state energy calculation in `run_chem`, "
"since it depends on pyscf, which is not available on Windows. "
"We will work it out in the near future, sorry for the inconvenience.")
warnings.warn(message=warning_msg)
# 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.
r"""
化学模块的 ansatz
"""
from .hardware_efficient import HardwareEfficientModel
from .rhf import RestrictHartreeFockModel
# 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.
"""
Hardware efficient ansatz 量子电路,以
`Hardware-efficient variational quantum eigensolver
for small molecules and quantum magnets` 方式构建。
具体细节可以参见 https://arxiv.org/abs/1704.05018
该模块依赖于
- paddlepaddle
- paddle_quantum
- ../layers
- ../qmodel
"""
import paddle
from paddle import nn
from paddle_quantum.circuit import UAnsatz
from ..qmodel import QModel
from .. import layers
class HardwareEfficientModel(QModel):
r"""面向硬件的量子线路。
Args:
num_qubit (int): 量子线路的量子比特数量。
circuit_depth (int): Cross resonance 和 Euler 转动层的数量。
"""
def __init__(self, num_qubit: int, circuit_depth: int) -> None:
super().__init__(num_qubit)
mid_layers = []
for i in range(circuit_depth):
mid_layers.append(layers.CrossResonanceLayer(num_qubit))
mid_layers.append(layers.EulerRotationLayer(num_qubit))
self.model = nn.Sequential(
layers.RotationLayer(num_qubit, "X"),
layers.RotationLayer(num_qubit, "Z"),
*mid_layers,
)
def forward(
self,
state: "paddle.Tensor[paddle.complex128]"
) -> "paddle.Tensor[paddle.complex128]":
r"""运行量子电路
Args:
state (paddle.Tensor[paddle.complex128]): 传入量子线路的量子态。
Returns:
paddle.Tensor[paddle.complex128]: 运行电路后的量子态
"""
out = self.model(state)
cir0 = UAnsatz(self._n_qubit)
for subcir in self.model:
cir0 += subcir.circuit
self._circuit = cir0
return out
# 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.
"""
Restrict Hartree Fock 模块
"""
from collections import OrderedDict
from copy import deepcopy
import numpy as np
import paddle
from paddle.nn import initializer
from paddle_quantum.circuit import UAnsatz
from ..linalg import givens_decomposition, parameters_to_givens_matrix2
from ..qmodel import QModel
from .. import functional
class _MakeGivensMatrix(paddle.autograd.PyLayer):
r"""Construct Givens rotation matrix G from parameters \theta and \phi.
.. math::
G[j-1,j-1] = \cos(\theta)
G[j,j] = \cos(\theta)
G[j-1,j] = -\phi\sin(\theta)
G[j,j-1] = \phi\sin(\theta)
We define this function since paddle doesn't fully support differentiate over
copy and slice operation, e.g. A[i,j] = \theta, where \theta is the parameter
to be differentiated.
"""
@staticmethod
def forward(ctx, theta: paddle.Tensor, phi: paddle.Tensor, j: int, n: int):
G = parameters_to_givens_matrix2(theta, phi, j, n)
ctx.saved_index = j
ctx.save_for_backward(theta, phi)
return G
@staticmethod
def backward(ctx, dG):
j = ctx.saved_index
theta, phi = ctx.saved_tensor()
dtheta = (-1.0 * (dG[j - 1, j - 1] + dG[j, j]) * paddle.sin(theta)
+ (dG[j, j - 1] - dG[j - 1, j]) * phi * paddle.cos(theta))
return dtheta, None
class RestrictHartreeFockModel(QModel):
r"""限制性 Hartree Fock (RHF) 波函数的量子线路。
Args:
num_qubits (int): RHF 计算中需要使用的量子比特数量。
n_electrons (int): 待模拟的量子化学系统中的电子数量。
onebody (paddle.Tensor(dtype=paddle.float64)): 经过 L\"owdin 正交化之后的单体积分。
"""
def __init__(
self,
num_qubits: int,
n_electrons: int,
onebody: paddle.Tensor
) -> None:
super().__init__(num_qubits)
self.nocc = n_electrons // 2
self.norb = num_qubits // 2
self.nvir = self.norb - self.nocc
givens_angles = self.get_init_givens_angles(onebody)
models = []
for ij, (theta, phi) in givens_angles.items():
models.append((ij, _GivensBlock(self.n_qubit, -theta, phi)))
self.models = paddle.nn.Sequential(*models)
def get_init_givens_angles(self, onebody: paddle.Tensor) -> OrderedDict:
r"""利用单体积分来初始化 Givens 旋转的角度。
Args:
onebody (paddle.Tensor): 经过 L\"owdin 正交化之后的单体积分。
Returns:
OrderedDict
"""
assert type(onebody) == paddle.Tensor, "The onebody integral must be a paddle.Tensor."
_, U = np.linalg.eigh(onebody.numpy())
U_tensor = paddle.to_tensor(U)
return givens_decomposition(U_tensor)
def forward(self, state: paddle.Tensor) -> paddle.Tensor:
r"""运行量子电路
Args:
state (paddle.Tensor[paddle.complex128]): 传入量子线路的量子态矢量。
Returns:
paddle.Tensor[paddle.complex128]: 运行电路后的量子态
"""
s = deepcopy(state)
self._circuit = UAnsatz(self.n_qubit)
for ij, givens_ops in self.models.named_children():
i, j = [int(p) for p in ij.split(",")]
s = givens_ops(s, 2 * i, 2 * j)
self._circuit += givens_ops.circuit
s = givens_ops(s, 2 * i + 1, 2 * j + 1)
self._circuit += givens_ops.circuit
return s
def single_particle_U(self):
r"""获取 Hartree Fock 轨道旋转矩阵
Returns:
paddle.Tensor, Hartree Fock 轨道旋转矩阵,:math:`n_{orbitals}\times n_{occ}`
"""
self.register_buffer("_U", paddle.eye(int(self.norb), dtype=paddle.float64))
for ij, givens_ops in self.models.named_children():
j = int(ij.split(",")[1])
self._U = givens_ops.single_particle_U(j, self.norb) @ self._U
return self._U[:, :self.nocc]
# !/usr/bin/env python3
# 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.
"""
用于构建量子电路层的函数操作。
该模块依赖于 paddlepaddle 和 paddle_quantum
"""
import paddle
from paddle_quantum.circuit import UAnsatz
# Rotation layer function
def rot_layer(
cir: UAnsatz,
parameters: "paddle.Tensor[paddle.float64]",
gate_type: str
) -> UAnsatz:
r"""该函数用来在量子线路上添加一层单比特旋转门,"Rx", "Ry", "Rz"
Args:
cir (UAnsatz): 量子线路
parameters (paddle.Tensor[paddle.float64]): 旋转门的旋转角度
gate_type (str): "X", "Y" 和 "Z",例如:如果是 "Rx" 门,则添 "X"
Returns:
UAnsatz
"""
n_qubits = cir.n
assert n_qubits == len(parameters), \
"length of the parameters must equal the number of qubits"
for i in range(n_qubits):
if gate_type == "X":
cir.rx(parameters[i], i)
elif gate_type == "Y":
cir.ry(parameters[i], i)
elif gate_type == "Z":
cir.rz(parameters[i], i)
return cir
# Euler rotation gate function
def euler_rotation(
cir: UAnsatz,
which_qubit: int,
angles: "paddle.Tensor[paddle.float64]",
) -> UAnsatz:
r"""该函数定义了单比特的 Euler 旋转门(使用 ZXZ 规范)
.. math::
U(\theta,\phi,\gamma)=e^{-i\gamma/2\hat{Z}}e^{-i\phi/2\hat{X}}e^{-i\theta/2\hat{X}}.
Args:
cir (UAnsatz): 量子线路
which (int): Euler 旋转门作用的量子比特编号
angles (paddle.Tensor[paddle.float64]): Euler 角,存储顺序与 ZXZ 操作的顺序相反。
Returns:
UAnsatz
"""
cir.rz(angles[0], which_qubit)
cir.rx(angles[1], which_qubit)
cir.rz(angles[2], which_qubit)
return cir
# Euler rotation layer function
def euler_rotation_layer(
cir: UAnsatz,
parameters: "paddle.Tensor[paddle.float64]",
) -> UAnsatz:
r"""该函数会在给定的量子线路上添加一层 Euler 旋转门。
Args:
cir (UAnsatz): 量子线路。
parameters (paddle.Tensor[paddle.float64]): Euler 角参数集合。
"""
n_qubits = cir.n
assert len(
parameters) == 3 * n_qubits, "length of parameter should be 3 times of the number of qubits in the circuit."
for i in range(n_qubits):
cir = euler_rotation(cir, i, parameters[3 * i:3 * (i + 1)])
return cir
# Cross resonance gate function
def cross_resonance(
cir: UAnsatz,
ctrl_targ: "list[int]",
phase_angle: paddle.Tensor
) -> UAnsatz:
r"""该函数定义了一个双比特的 cross resonance (CR) 门。
.. math::
U(\theta) = \exp(-i\frac{\theta}{2}\hat{X}\otimes\hat{Z})
Args:
cir (UAnsatz): 量子线路。
ctrl_targ (list[int]): 控制比特和目标比特对应的比特编号。
phase_angle (paddle.Tensor[paddle.float64]): 旋转角度。
Returns:
UAnsatz
"""
cir.h(ctrl_targ[0])
cir.rzz(phase_angle, ctrl_targ)
cir.h(ctrl_targ[0])
return cir
# Cross resonance layer function
def cr_layer(
cir: UAnsatz,
parameters: "paddle.Tensor[paddle.float64]",
ctrl_qubit_index: "list[int]",
targ_qubit_index: "list[int]"
) -> UAnsatz:
"""该函数在给定线路上按照给定的控制和目标比特编号添加一层 cross resonance (CR) 门。
Args:
cir (UAnsatz): 量子线路。
parameters (paddle.Tensor[paddle.float64]): CR 门中的角度。
ctrl_qubit_index (list[int]): 控制比特序号。
targ_qubit_index (list[int]): 目标比特序号。
Returns:
UAnsatz
"""
assert len(parameters) == len(ctrl_qubit_index) and len(ctrl_qubit_index) == len(targ_qubit_index), \
"length of parameter must be the same as the number of cr gates"
for i, ct_index in enumerate(zip(ctrl_qubit_index, targ_qubit_index)):
cir = cross_resonance(cir, list(ct_index), parameters[i])
return cir
# Nearest neighbor Givens rotation gate function
def givens_rotation(
cir: UAnsatz,
theta: "paddle.Tensor[paddle.float64]",
q1_index: int,
q2_index: int
) -> UAnsatz:
r"""该函数定义了两个相邻比特之间的 Givens 旋转门。详细信息参见 https://arxiv.org/abs/1711.05395.
Note:
在 paddlequantum :math:`Ry(\theta)=e^{-i\frac{\theta}{2}\hat{Y}}`.
Args:
cir (UAnsatz): 量子线路。
theta (paddle.Tensor[paddle.float64]): 操作中 Ry 门的角度。
q1_index (int): 第一个 qubit 的编号。
q2_index (int): 第二个 qubit 的编号。
Returns:
UAnsatz
"""
cir.cnot([q2_index, q1_index])
cir.cry(-2 * theta, [q1_index, q2_index])
cir.cnot([q2_index, q1_index])
return cir
# !/usr/bin/env python3
# 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.
"""
量子电路层,该模块依赖于 paddlepaddle,paddle_quantum 和 math 包。
同时依赖于 qmodel 和 functional 模块。
"""
import math
import paddle
from paddle.nn import initializer
from paddle_quantum.circuit import UAnsatz
from .qmodel import QModel
from . import functional
# Rotation layer
class RotationLayer(QModel):
r"""单比特旋转门层。
Args:
num_qubits (int): 量子线路的量子比特数。
gate_type (str): 量子门的类型,"X", "Y" 和 "Z" 中的一个。
trainable (bool): 层中的角度参数是否可训练。
"""
def __init__(self, num_qubits: int, gate_type: str, trainable: bool = True):
super().__init__(num_qubits)
self._angle_attr = paddle.ParamAttr(
initializer=initializer.Uniform(0.0, 2*math.pi),
trainable=trainable
)
self.angles = self.create_parameter(
shape=[num_qubits],
attr=self._angle_attr,
dtype="float64"
)
self._gate_type = gate_type
def forward(
self,
state: "paddle.Tensor[paddle.complex128]"
) -> "paddle.Tensor[paddle.complex128]":
r"""获取运行后的量子态
Args:
state (paddle.Tensor[paddle.complex128, shape=[n]]): 送入电路的量子态
Returns:
paddle.Tensor[paddle.complex128, shape=[n]]: 运行电路后的量子态
"""
cir0 = UAnsatz(self._n_qubit)
self._circuit = functional.rot_layer(cir0, self.angles, self._gate_type)
return self.circuit.run_state_vector(state)
def extra_repr(self):
r"""额外表示
"""
return "gate={:s}, dtype={:s}".format(
self._gate_type,
self.angles.dtype.name)
# Euler rotation layer
class EulerRotationLayer(QModel):
r"""Euler 旋转门层。
Args:
num_qubits (int): 量子线路中的量子比特数量。
trainable (bool): 层中的参数是否是可训练的。
"""
def __init__(self, num_qubits: int, trainable: bool = True) -> None:
super().__init__(num_qubits)
self._angle_attr = paddle.ParamAttr(
initializer=initializer.Uniform(0.0, 2*math.pi),
trainable=trainable
)
self.euler_angles = self.create_parameter(
shape=[3*num_qubits],
attr=self._angle_attr,
dtype="float64"
)
def forward(
self,
state: "paddle.Tensor[paddle.complex128]"
) -> "paddle.Tensor[paddle.complex128]":
r"""获取运行后的量子态
Args:
state (paddle.Tensor[paddle.complex128, shape=[n]]): 送入电路的量子态
Returns:
paddle.Tensor[paddle.complex128, shape=[n]]: 运行电路后的量子态
"""
cir0 = UAnsatz(self._n_qubit)
self._circuit = functional.euler_rotation_layer(cir0, self.euler_angles)
return self._circuit.run_state_vector(state)
def extra_repr(self):
r"""额外表示
"""
return "dtype={:s}".format(self.euler_angles.dtype.name)
# Cross resonance layer
class CrossResonanceLayer(QModel):
r"""在量子线路中按照给定的控制和目标比特添加一层 cross resonance 门。
Args:
num_qubits (int): 量子比特数目。
ctrl_qubit_index (list[int]): 控制比特的序号。
targ_qubit_index (list[int]): 目标比特的序号。
trainable (bool): 层中的参数是否可训练。
"""
def __init__(
self,
num_qubits: int,
ctrl_qubit_index: "list[int]" = None,
targ_qubit_index: "list[int]" = None,
trainable: bool = True
) -> None:
super().__init__(num_qubits)
if ctrl_qubit_index is None:
ctrl_qubit_index = list(range(num_qubits))
if targ_qubit_index is None:
targ_qubit_index = list(range(1, num_qubits)) + [0]
self._ctrl_qubit_index = ctrl_qubit_index
self._targ_qubit_index = targ_qubit_index
self._phase_attr = paddle.ParamAttr(
initializer=initializer.Uniform(0.0, 2*math.pi),
trainable=trainable
)
self.phase = self.create_parameter(
shape=[len(ctrl_qubit_index)],
attr=self._phase_attr,
dtype="float64"
)
def forward(
self,
state: "paddle.Tensor[paddle.complex128]"
) -> "paddle.Tensor[paddle.complex128]":
r"""获取运行后的量子态
Args:
state (paddle.Tensor[paddle.complex128, shape=[n]]): 送入电路的量子态
Returns:
paddle.Tensor[paddle.complex128, shape=[n]]: 运行电路后的量子态
"""
cir0 = UAnsatz(self._n_qubit)
self._circuit = functional.cr_layer(
cir0,
self.phase,
self._ctrl_qubit_index,
self._targ_qubit_index)
return self._circuit.run_state_vector(state)
def extra_repr(self):
r"""额外表示
"""
return "dtype={:s}".format(self.phase.dtype.name)
此差异已折叠。
# !/usr/bin/env python3
# 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.
"""
从分子结构等信息中提取量子化学需要的输入。
"""
from typing import Tuple, List
import numpy as np
from pyscf import gto, scf
from pyscf.lo import lowdin
# Transform one and two body integral into L\"owdin basis
def lowdin_transform(
ovlp: np.array,
onebody: np.array,
twobody: np.array
) -> Tuple[np.array]:
r"""该函数会将 pyscf 中得到的高斯积分利用 L\"owdin 正交化方法进行变换。
Note:
L\"owdin 正交化:
:math:`S_{ij}=\langle\phi_i^{\text{G}}|\phi_j^{\text{G}}\rangle`,
:math:`X = S^{-1/2}`
Operators 的变换方式:
:math:`A^{\prime}_{ij}=\sum_{pq}A_{pq}X_{ip}X_{qj}`
:math:`B^{\prime}_{iklj}=\sum_{pqrs}B_{prsq}X_{ip}X_{kr}X_{sl}X_{qj}`
分子轨道的变换方式:
:math:`C^{\prime}_{ij}=\sum_{p}C_{pj}X^{-1}_{ip}`
Args:
ovlp (np.array): 交叠积分,`mol.intor("int1e_ovlp")`。
onebody (np.array): 单体积分,`mol.intor("int1e_kin")+mol.intor("int1e_nuc")`。
twobody (np.array): 两体积分,`mol.intor("int2e")`。
Returns:
Tuple[np.array]:
- 变换之后的单体积分。
- 变换之后的两体积分。
"""
inv_half_ovlp = lowdin(ovlp)
t_onebody = inv_half_ovlp @ onebody @ inv_half_ovlp
t_twobody = np.einsum(
"pqrs,ip,qj,kr,sl->ijkl",
twobody, inv_half_ovlp, inv_half_ovlp, inv_half_ovlp, inv_half_ovlp
)
return t_onebody, t_twobody
# Molecular information
def get_molecular_information(
geometry: List[Tuple[str, List]],
basis: str = "sto-3g",
charge: int = 0,
debug: bool = False
) -> Tuple:
r"""该函数会返回量子化学(目前是 "hartree fock" 方法)计算所需要的分子信息,包括有计算需要的量子比特的数量,分子中的电子数,分子积分和 pyscf 平均场结果 (optional)。
Args:
geometry (List[Tuple[str,List]]): 分子中各原子笛卡尔坐标;
basis (str): 基函数名称,例如:"sto-3g";
charge (int): 分子的电荷;
debug (bool): 是否使用 debug 模式。debug 模式会返回 pyscf 的平均场计算结果。
Returns:
Tuple:
- 量子比特数目;
- 分子中的电子数;
- 原子核之间的排斥能、单体积分、双体积分;
- pyscf 的平均场计算结果 (可选,只有 debug=True 才会返回)。
"""
mol = gto.M(atom=geometry, basis=basis, charge=charge, unit="angstrom")
mol.build()
if debug:
mf_mol = scf.RHF(mol).run()
int_ovlp = mol.intor("int1e_ovlp")
nuc_energy = mol.energy_nuc()
onebody = mol.intor("int1e_kin") + mol.intor("int1e_nuc")
twobody = mol.intor("int2e")
orth_onebody, orth_twobody = lowdin_transform(int_ovlp, onebody, twobody)
if debug:
return 2*mol.nao, mol.nelectron, (nuc_energy, orth_onebody, 0.5*orth_twobody), mf_mol
else:
return 2*mol.nao, mol.nelectron, (nuc_energy, orth_onebody, 0.5*orth_twobody)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册