提交 39ce5851 编写于 作者: Q Quleaf

first commit

first commit

readme update
上级 2718bc2a
.idea
__pycache__/
output
*.egg-info
.ipynb_checkpoints
\ No newline at end of file
- repo: https://github.com/PaddlePaddle/mirrors-yapf.git
sha: 0d79c0c469bab64f7229c9aca2b1186ef47f0e37
hooks:
- id: yapf
files: \.py$
- repo: https://github.com/pre-commit/pre-commit-hooks
sha: a11d9314b22d8f8c7556443875b731ef05965464
hooks:
- id: check-merge-conflict
- id: check-symlinks
- id: detect-private-key
files: (?!.*paddle)^.*$
- id: end-of-file-fixer
files: \.md$
- id: trailing-whitespace
files: \.md$
- repo: https://github.com/Lucas-C/pre-commit-hooks
sha: v1.0.1
hooks:
- id: forbid-crlf
files: \.md$
- id: remove-crlf
files: \.md$
- id: forbid-tabs
files: \.md$
- id: remove-tabs
files: \.md$
- repo: local
hooks:
- id: copyright_checker
name: copyright_checker
entry: python ./tools/copyright.hook
language: system
files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto|py)$
exclude: (?!.*third_party)^.*$ | (?!.*book)^.*$
\ No newline at end of file
Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserve.
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.
\ No newline at end of file
# Quantum
\ No newline at end of file
# Paddle Quantum (量桨)
Paddle Quantum(量桨)是基于百度飞桨开发的量子机器学习工具集,支持量子神经网络的搭建与训练,提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,使得百度飞桨也因此成为国内首个目前也是唯一一个支持量子机器学习的深度学习框架。
![](https://release-data.cdn.bcebos.com/Paddle%20Quantum.png)
量桨建立起了人工智能与量子计算的桥梁,不但可以快速实现量子神经网络的搭建与训练,还提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,并提供多项自研量子机器学习应用。通过百度飞桨深度学习平台赋能量子计算,量桨为领域内的科研人员以及开发者便捷地开发量子人工智能的应用提供了强有力的支撑,同时也为广大量子计算爱好者提供了一条可行的学习途径。
## 特色
- 易用性:提供简洁的神经网络搭建与丰富的量子机器学习案例。
- 通用性与拓展性:支持常用量子电路模型,提供多项优化工具。
- 特色工具集:提供量子优化、量子化学等前沿量子应用工具集,自研多项量子机器学习应用。
## 安装步骤
### Install PaddlePaddle
请参考 [PaddlePaddle](https://www.paddlepaddle.org.cn/documentation/docs/zh/beginners_guide/index_cn.html) 安装配置页面。此项目需求 PaddlePaddle 1.8.0 或更高版本。
### 下载 Paddle Quantum 并安装
```bash
git clone http://github.com/PaddlePaddle/quantum
```
```bash
cd quantum
pip install -e .
```
### 或使用 requirements.txt 安装依赖包
```bash
python -m pip install --upgrade -r requirements.txt
```
### 使用 openfermion 读取xyz 描述文件 (仅可在linux下安装使用)
VQE中调用 openfermion 读取分子xyz文件并计算,因此需要安装 openfermion 和 openfermionpyscf。
```bash
pip install openfermion
pip install openfermionpyscf
```
### 运行
```bash
cd paddle_quantum/QAOA/example
python main.py
```
## 入门与开发
### 教程入门
量子计算是由量子力学与计算理论交叉而成的全新计算模型,具有强大的信息处理优势和广阔的应用前景,被视作未来计算技术的心脏。量子计算的相关介绍与入门知识可以参考 [1-3]。
量子机器学习是一门结合量子计算与机器学习的交叉学科,一方面利用量子计算的信息处理优势促进人工智能的发展,另一方面也利用现有的人工智能的技术突破量子计算的研发瓶颈。关于量子机器学习的入门资料可以参考 [4-6]。Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为量子机器学习领域的研发提供强有力的支撑,也提供了丰富的案例供开发者学习。
### 案例入门
特别的,我们提供了涵盖量子优化、量子化学、量子机器学习等多个领域的案例供大家学习。比如:
- 量子组合优化(QAOA),完成安装步骤后打开 tutorial\QAOA.ipynb 即可进行研究学习。
```bash
cd tutorial
jupyter notebook QAOA.ipynb
```
- 量子特征求解器(VQE),完成安装步骤后打开 tutorial\VQE.ipynb 即可进行研究学习。
```
cd tutorial
jupyter notebook VQE.ipynb
```
### 开发
Paddle Quantum 使用 setuptools的develop 模式进行安装,相关代码修改可以直接进入`paddle_quantum` 文件夹进行修改。python 文件携带了自说明注释。
## 交流与反馈
- 我们非常欢迎您欢迎您通过[Github Issues](https://github.com/PaddlePaddle/Quantum/issues)来提交问题、报告与建议。
- QQ技术交流群: 1076223166
## 使用Paddle Quantum的工作
我们非常欢迎开发者使用Paddle Quantum进行量子机器学习的研发,如果您的工作有使用Paddle Quantum,也非常欢迎联系我们。目前使用 Paddle Quantum 的代表性工作关于 Gibbs 态制备如下:
[1] Y. Wang, G. Li, and X. Wang, “Variational quantum Gibbs state preparation with a truncated Taylor series,” arXiv:2005.08797, May 2020. [[pdf](https://arxiv.org/pdf/2005.08797.pdf)]
## Copyright and License
Paddle Quantum 使用 [Apache-2.0 license](LICENSE)许可证。
## References
[1] [量子计算 - 百度百科](https://baike.baidu.com/item/量子计算/11035661?fr=aladdin)
[2] M. A. Nielsen and I. L. Chuang, Quantum computation and quantum information. Cambridge university press, 2010.
[3] Phillip Kaye, R. Laflamme, and M. Mosca, An Introduction to Quantum Computing. 2007.
[4] J. Biamonte, P. Wittek, N. Pancotti, P. Rebentrost, N. Wiebe, and S. Lloyd, “Quantum machine learning,” Nature, vol. 549, no. 7671, pp. 195–202, Sep. 2017. [[pdf](https://arxiv.org/pdf/1611.09347)]
[5] M. Schuld, I. Sinayskiy, and F. Petruccione, “An introduction to quantum machine learning,” Contemp. Phys., vol. 56, no. 2, pp. 172–185, 2015. [[pdf](https://arxiv.org/pdf/1409.3097)]
[6] M. Benedetti, E. Lloyd, S. Sack, and M. Fiorentini, “Parameterized quantum circuits as machine learning models,” Quantum Sci. Technol., vol. 4, no. 4, p. 043001, Nov. 2019. [[pdf](https://arxiv.org/pdf/1906.07682)]
# Copyright (c) 2020 Paddle Quantum Authors. 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.
"""
HGenerator
"""
from numpy import array, kron, trace
import scipy
__all__ = ["H_generator", ]
def H_generator():
"""
Generate a Hamiltonian with trivial descriptions
Returns: A Hamiltonian
"""
beta = 1
sigma_I = array([[1, 0], [0, 1]])
sigma_Z = array([[1, 0], [0, -1]])
H = (-kron(kron(sigma_Z, sigma_Z), sigma_I) - kron(
kron(sigma_I, sigma_Z), sigma_Z) - kron(
kron(sigma_Z, sigma_I), sigma_Z))
rho = scipy.linalg.expm(-1 * beta *
H) / trace(scipy.linalg.expm(-1 * beta * H))
return H.astype("complex64"), rho.astype("complex64")
# Copyright (c) 2020 Paddle Quantum Authors. 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_GIBBS
"""
from numpy import concatenate, zeros
from numpy import pi as PI
from paddle import fluid
from paddle.complex import matmul, transpose, trace
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import compute_fid, partial_trace
from paddle_quantum.GIBBS.HGenerator import H_generator
SEED = 1
__all__ = [
"U_theta",
"Net",
"Paddle_GIBBS",
]
def U_theta(theta, input_state, N, D): # definition of U_theta
"""
:param theta:
:param input_state:
:return:
"""
cir = UAnsatz(N, input_state=input_state)
for i in range(N):
cir.rx(theta=theta[0][0][i], which_qubit=i + 1)
cir.ry(theta=theta[0][1][i], which_qubit=i + 1)
cir.rx(theta=theta[0][2][i], which_qubit=i + 1)
for repeat in range(D):
for i in range(1, N):
cir.cnot(control=[i, i + 1])
for i in range(N):
cir.ry(theta=theta[repeat][0][i], which_qubit=i + 1)
# cir.ry(theta=theta[repeat][1][i], which_qubit=i + 1)
# cir.ry(theta=theta[repeat][2][i], which_qubit=i + 1)
return cir.state
class Net(fluid.dygraph.Layer):
"""
Construct the model net
"""
def __init__(self,
shape,
param_attr=fluid.initializer.Uniform(
low=0.0, high=PI, seed=SEED),
dtype='float32'):
super(Net, self).__init__()
self.theta = self.create_parameter(
shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
def forward(self, input_state, H, N, N_SYS_B, D):
"""
Args:
input_state: The initial state with default |0..>
H: The target Hamiltonian
Returns:
The loss.
"""
out_state = U_theta(self.theta, input_state, N, D)
# rho_AB = utils.matmul(utils.matrix_conjugate_transpose(out_state), out_state)
rho_AB = matmul(
transpose(
fluid.framework.ComplexVariable(out_state.real,
-out_state.imag),
perm=[1, 0]),
out_state)
# compute the partial trace and three losses
rho_B = partial_trace(rho_AB, 2**(N - N_SYS_B), 2**(N_SYS_B), 1)
rho_B_squre = matmul(rho_B, rho_B)
loss1 = (trace(matmul(rho_B, H))).real
loss2 = (trace(rho_B_squre)).real * 2
loss3 = -(trace(matmul(rho_B_squre, rho_B))).real / 2
loss = loss1 + loss2 + loss3 # 损失函数
# option: if you want to check whether the imaginary part is 0, uncomment the following
# print('loss_iminary_part: ', loss.numpy()[1])
return loss - 3 / 2, rho_B
def Paddle_GIBBS(hamiltonian, rho=None, N=5, N_SYS_B=3, D=1, ITR=100, LR=0.5):
"""
Paddle_GIBBS
"""
with fluid.dygraph.guard():
# initial state preparing
_initial_state_np = concatenate(
([[1.]], zeros([1, 2**N - 1])), axis=1).astype('complex64')
initial_state = fluid.dygraph.to_variable(_initial_state_np)
# gibbs Hamiltonian preparing
H = fluid.dygraph.to_variable(hamiltonian)
# net
net = Net(shape=[D + 1, 3, N])
# optimizer
opt = fluid.optimizer.AdamOptimizer(
learning_rate=LR, parameter_list=net.parameters())
# gradient descent loop
for itr in range(1, ITR + 1):
loss, rho_B = net(initial_state, H, N, N_SYS_B, D)
loss.backward()
opt.minimize(loss)
net.clear_gradients()
rho_B = rho_B.numpy()
if rho is not None:
fid = compute_fid(rho_B, rho)
print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:',
'%.4f' % fid)
return rho_B
def main():
"""
main
"""
# gibbs Hamiltonian preparing
hamiltonian, rho = H_generator()
rho_B = Paddle_GIBBS(hamiltonian, rho)
print(rho_B)
if __name__ == '__main__':
main()
# Copyright (c) 2020 Paddle Quantum Authors. 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.
"""
main
"""
from paddle_quantum.GIBBS.HGenerator import H_generator
from paddle_quantum.GIBBS.Paddle_GIBBS import Paddle_GIBBS
def main():
hamiltonian, rho = H_generator()
rho_B = Paddle_GIBBS(hamiltonian, rho)
print(rho_B)
if __name__ == '__main__':
main()
# Copyright (c) 2020 Paddle Quantum Authors. 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.
"""
main
"""
from paddle_quantum.GIBBS.HGenerator import H_generator
from paddle_quantum.GIBBS.Paddle_GIBBS import Paddle_GIBBS
def main():
# gibbs Hamiltonian preparing
hamiltonian, rho = H_generator()
rho_B = Paddle_GIBBS(hamiltonian, rho)
print(rho_B)
if __name__ == '__main__':
main()
# Copyright (c) 2020 Paddle Quantum Authors. 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 os
from paddle import fluid
from paddle.complex import matmul as pp_matmul
from paddle.complex import transpose
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator
from numpy import ones, abs, conjugate, real, savez, sqrt, zeros
from numpy import matmul as np_matmul
from numpy import pi as PI
# Random seed for optimizer
SEED = 1
__all__ = [
"circuit_QAOA",
"circuit_extend_QAOA",
"Net",
"Paddle_QAOA",
]
def circuit_QAOA(theta, input_state, adjacency_matrix, N, P):
"""
This function constructs the parameterized QAOA circuit which is composed of P layers of two blocks:
one block is U_theta[layer][0] based on the problem Hamiltonian H which encodes the classical problem,
and the other is U_theta[layer][1] constructed from the driving Hamiltonian describing the rotation around Pauli X
acting on each qubit. It finally outputs the final state of the QAOA circuit.
Args:
theta: parameters to be optimized in the QAOA circuit
input_state: initial state of the QAOA circuit which usually is the uniform superposition of 2^N bit-strings
in the computational basis $|0\rangle, |1\rangle$
adjacency_matrix: the adjacency matrix of the graph encoding the classical problem
N: number of qubits, or equivalently, the number of nodes in the given graph
P: number of layers of two blocks in the QAOA circuit
Returns:
the final state of the QAOA circuit: cir.state
"""
cir = UAnsatz(N, input_state=input_state)
# The first loop defines the QAOA circuit with P layers of two blocks
for layer in range(P):
# The second and third loops aim to construct the first block U_theta[layer][0] which involves
# two-qubit operation e^{-i\beta Z_iZ_j} acting on a pair of qubits or nodes i and j in the circuit.
for row in range(N):
for col in range(N):
if abs(adjacency_matrix[row, col]) and row < col:
cir.cnot([row + 1, col + 1])
cir.rz(
theta=theta[layer][0] * adjacency_matrix[row, col],
which_qubit=col + 1, )
cir.cnot([row + 1, col + 1])
# This loops constructs the second block U_theta only involving the single-qubit operation e^{-i\beta X}.
for i in range(1, N + 1):
cir.rx(theta=theta[layer][1], which_qubit=i)
return cir.state
def circuit_extend_QAOA(theta, input_state, adjacency_matrix, N, P):
"""
This is an extended version of the QAOA circuit, and the main difference is U_theta[layer]([1]-[3]) constructed
from the driving Hamiltonian describing the rotation around an arbitrary direction on each qubit.
Args:
theta: parameters to be optimized in the QAOA circuit
input_state: input state of the QAOA circuit which usually is the uniform superposition of 2^N bit-strings
in the computational basis
adjacency_matrix: the adjacency matrix of the problem graph encoding the original problem
N: number of qubits, or equivalently, the number of parameters in the original classical problem
P: number of layers of two blocks in the QAOA circuit
Returns:
final state of the QAOA circuit: cir.state
Note: If this U_extend_theta function is used to construct QAOA circuit, then we need to change the parameter layer
in the Net function defined below from the Net(shape=[D, 2]) for U_theta function to Net(shape=[D, 4])
because the number of parameters doubles in each layer in this QAOA circuit.
"""
cir = UAnsatz(N, input_state=input_state)
# The first loop defines the QAOA circuit with P layers of two blocks
for layer in range(P):
# The second and third loops aim to construct the first block U_theta[layer][0] which involves
# two-qubit operation e^{-i\beta Z_iZ_j} acting on a pair of qubits or nodes i and j in the circuit.
for row in range(N):
for col in range(N):
if abs(adjacency_matrix[row, col]) and row < col:
cir.cnot([row + 1, col + 1])
cir.rz(
theta=theta[layer][0] * adjacency_matrix[row, col],
which_qubit=col + 1, )
cir.cnot([row + 1, col + 1])
# This loops constructs the second block U_theta[layer][1]-[3] composed of three single-qubit operation
# e^{-i\beta[1] Z}e^{-i\beta[2] X}e^{-i\beta[3] X} sequentially acting on single qubits.
for i in range(1, N + 1):
cir.rz(theta=theta[layer][1], which_qubit=i)
cir.rx(theta=theta[layer][2], which_qubit=i)
cir.rz(theta=theta[layer][3], which_qubit=i)
return cir.state
class Net(fluid.dygraph.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,
shape,
param_attr=fluid.initializer.Uniform(
low=0.0, high=PI, seed=SEED),
dtype="float32", ):
super(Net, self).__init__()
self.theta = self.create_parameter(
shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
def forward(self, input_state, adjacency_matrix, out_state_store, N, P,
METHOD):
"""
This function constructs the loss function for the QAOA circuit.
Args:
self: the free parameters to be optimized in the QAOA circuit and defined in the above function
input_state: initial state of the QAOA circuit which usually is the uniform superposition of 2^N bit-strings
in the computational basis $|0\rangle, |1\rangle$
adjacency_matrix: the adjacency matrix generated from the graph encoding the classical problem
out_state_store: the output state of the QAOA circuit
N: number of qubits
P: number of layers
METHOD: which version of QAOA is chosen to solve the problem, i.e., standard version labeled by 1 or
extended version by 2.
Returns:
The loss function for the parameterized QAOA circuit.
"""
# Generate the problem_based quantum Hamiltonian H_problem based on the classical problem in paddle
H, _ = H_generator(N, adjacency_matrix)
H_problem = fluid.dygraph.to_variable(H)
# The standard QAOA circuit: the function circuit_QAOA is used to construct the circuit, indexed by METHOD 1.
if METHOD == 1:
out_state = circuit_QAOA(self.theta, input_state, adjacency_matrix,
N, P)
# The extended QAOA circuit: the function circuit_extend_QAOA is used to construct the net, indexed by METHOD 2.
elif METHOD == 2:
out_state = circuit_extend_QAOA(self.theta, input_state,