<jupyter_start><jupyter_text>吉布斯态的制备  Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.   概览在本案例中，我们将展示如何通过 Paddle Quantum 训练量子神经网络（quantum neural network, QNN）来制备量子吉布斯态。  背景量子计算中的前沿方向包含量子机器学习和量子优化，在这两个方向中，特定量子态的制备是非常重要的问题。特别的，吉布斯态（Gibbs state）的制备是实现诸多量子算法所必须的步骤并且广泛应用于：- 量子机器学习中受限波尔兹曼机的学习 [1]- 解决凸优化和半正定规划等优化问题 [2]- 组合优化问题 [3]具体的吉布斯态定义如下：给定一个 $n$ 量子比特的哈密顿量 $H$（一般来说这是一个$2^n\times2^n$的厄米矩阵），其在温度 $T$ 下的吉布斯态为  $$\rho_G = \frac{{{e^{ - \beta H}}}}{{\text{tr}({e^{ - \beta H}})}},\tag{1}$$ 其中 ${e^{ - \beta H}}$ 是矩阵 $ - \beta H$ 的矩阵指数，$\beta  = \frac{1}{{kT}}$ 是系统的逆温度参数，$T$ 是温度参数，$k$ 是玻尔兹曼常数 (这篇教程中我们取 $k = 1$)。  Paddle Quantum 实现 首先通过下面几行代码引入必要的 library 和 package。<jupyter_code>import scipy
from numpy import array, concatenate, zeros
from numpy import pi as PI
from numpy import trace as np_trace
import paddle
from paddle import matmul, trace, real
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.state import density_op
from paddle_quantum.utils import state_fidelity, partial_trace, pauli_str_to_matrix<jupyter_output><empty_output><jupyter_text>作为一个上手的例子，这里我们考虑一个 3 量子比特的哈密顿量及其吉布斯态：$$H = -Z \otimes Z \otimes I - I \otimes Z \otimes Z - Z \otimes I \otimes Z, \quad I=\left [\begin{matrix}1 & 0  \\0 & 1  \\\end{matrix} \right ], \quad Z=\left [\begin{matrix}1 & 0  \\0 & -1  \\\end{matrix} \right ].\tag{2}$$这个例子中，我们将逆温度参数设置为 $\beta = 1.5$。此外，为了方便测试结果，我们按照定义提前生成好了理想情况的吉布斯态 $\rho_G$。<jupyter_code>N = 4        # 量子神经网络的宽度
N_SYS_B = 3  # 用于生成吉布斯态的子系统B的量子比特数   
SEED = 16    # 固定随机种子
beta = 1.5   # 设置逆温度参数 beta
# 生成用泡利字符串表示的特定的哈密顿量
H = [[-1.0, 'z0,z1'], [-1.0, 'z1,z2'], [-1.0, 'z0,z2']]

# 生成哈密顿量的矩阵信息
hamiltonian = pauli_str_to_matrix(H, N_SYS_B)

# 生成理想情况下的目标吉布斯态 rho
rho_G = scipy.linalg.expm(-1 * beta * hamiltonian) / np_trace(scipy.linalg.expm(-1 * beta * hamiltonian))

# 设置成 Paddle quantum 所支持的数据类型
hamiltonian = hamiltonian.astype("complex128")
rho_G = rho_G.astype("complex128")<jupyter_output><empty_output><jupyter_text>搭建量子神经网络 - 在这个案例中，我们将通过训练量子神经网络（也可以理解为参数化量子电路）来制备吉布斯态。这里，我们提供一个简单的 4 量子比特的量子电路如下：  ![Ugibbs.jpg](https://release-data.cdn.bcebos.com/PIC%2FUgibbs.jpg)- 我们需要预设一些电路的参数，比如电路有 4 个量子比特，其中第 1 个量子比特是辅助系统，第 2-4 个量子比特是用以产生吉布斯态的子系统。- 初始化其中的变量参数，$\theta$ 代表我们量子神经网络中的参数组成的向量。         接下来我们根据上图中的电路设计，通过 Paddle Quantum 的 `UAnsatz` 类和内置的 `real_entangled_layer(theta, D)` 电路模板来高效搭建量子神经网络。<jupyter_code>def U_theta(initial_state, theta, N, D):
    """
    量子神经网络
    """
    
    # 按照量子比特数量/网络宽度初始化量子神经网络
    cir = UAnsatz(N)
    
    # 内置的 {R_y + CNOT} 电路模板
    cir.real_entangled_layer(theta[:D], D)
    
    # 铺上最后一层 R_y 旋转门
    for i in range(N):
        cir.ry(theta=theta[D][i][0], which_qubit=i)
        
    # 量子神经网络作用在给定的初始态上
    final_state = cir.run_density_matrix(initial_state)

    return final_state, cir<jupyter_output><empty_output><jupyter_text>配置训练模型——损失函数 - 现在我们已经有了数据和量子神经网络的架构，我们将进一步定义合适的训练参数、模型和损失函数来达到我们的目标。- 具体的我们参考的是论文 [4] 中的方法，核心思想是**利用吉布斯态达到了最小自由能**的性质。- 通过作用量子神经网络 $U(\theta)$ 在初始态上，我们可以得到输出态 $\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $，其在第 2-4 个量子比特的态记为 $\rho_B(\theta)$。- 设置训练模型中的的损失函数。在吉布斯态学习中，我们利用冯诺依曼熵函数的截断来进行自由能的估计，相应的损失函数参考 [4] 可以设为 $loss= {L_1} + {L_2} + {L_3}$，其中 $${L_1}= \text{tr}(H\rho_B), \quad {L_2} = 2{\beta^{-1}}{\text{tr}}(\rho_B^2), \quad L_3 = - {\beta ^{ - 1}}\big(\text{tr}(\rho_B^3) + 3\big)/2.\tag{3}$$<jupyter_code>class Net(paddle.nn.Layer):
    def __init__(self, shape, dtype='float64'):
        super(Net, self).__init__()
        
        # 初始化 theta 参数列表，并用 [0, 2*pi] 的均匀分布来填充初始值
        self.theta = self.create_parameter(shape=shape,
                                           default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),
                                           dtype=dtype, is_bias=False)
        
        # 初始化 rho = |0..0><0..0| 的密度矩阵
        self.initial_state = paddle.to_tensor(density_op(N))

    # 定义损失函数和前向传播机制
    def forward(self, H, N, N_SYS_B, D):

        # 施加量子神经网络
        rho_AB, cir = U_theta(self.initial_state, self.theta, N, D)

        # 计算偏迹 partial trace 来获得子系统B所处的量子态 rho_B
        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 = real(trace(matmul(rho_B, H)))
        loss2 = real(trace(rho_B_squre)) * 2 / beta
        loss3 = -(real(trace(matmul(rho_B_squre, rho_B))) + 3) / (2 * beta)
        
        # 最终的损失函数
        loss = loss1 + loss2 + loss3  

        return loss, rho_B, cir<jupyter_output><empty_output><jupyter_text>配置训练模型——模型参数 在进行量子神经网络的训练之前，我们还需要进行一些训练的超参数设置，主要是学习速率（learning rate, LR）、迭代次数（iteration, ITR）和量子神经网络计算模块的深度（depth, D）。这里我们设定学习速率为 0.5，迭代次数为 50 次。读者不妨自行调整来直观感受下超参数调整对训练效果的影响。<jupyter_code>ITR = 50 # 设置训练的总迭代次数
LR = 0.5 # 设置学习速率
D = 1    # 设置量子神经网络中重复计算模块的深度 Depth<jupyter_output><empty_output><jupyter_text>进行训练 - 当训练模型的各项参数都设置完成后，我们将数据转化为 Paddle 中的张量，进而进行量子神经网络的训练。- 训练过程中我们用的是 [Adam Optimizer](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/optimizer/adam/Adam_cn.html)，也可以调用 Paddle 中提供的其他优化器。- 我们将训练过程中的结果依次输出。- 特别地，我们依次输出了我们学习到的量子态 $\rho_B(\theta)$ 与吉布斯态 $\rho_G$ 的保真度，保真度越高说明QNN输出的态越接近于吉布斯态。<jupyter_code>paddle.seed(SEED)
    
# 我们需要将 Numpy array 转换成 Paddle 中支持的 Tensor
H = paddle.to_tensor(hamiltonian)

# 确定网络的参数维度
net = Net(shape=[D + 1, N, 1])

# 一般来说，我们利用 Adam 优化器来获得相对好的收敛，
# 当然你可以改成 SGD 或者是 RMS prop.
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())

# 优化循环
for itr in range(1, ITR + 1):
        
    # 前向传播计算损失函数并返回生成的量子态 rho_B
    loss, rho_B, cir = net(H, N, N_SYS_B, D)
        
    # 反向传播极小化损失函数
    loss.backward()
    opt.minimize(loss)
    opt.clear_grad()

    # 转换成 Numpy array 用以计算量子态的保真度 F(rho_B, rho_G)
    rho_B = rho_B.numpy()
    fid = state_fidelity(rho_B, rho_G)
        
    # 打印训练结果
    if itr % 10 == 0:
        print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:', '%.4f' % fid)
    if itr == ITR:
        print("\n训练后的电路：")
        print(cir)<jupyter_output>iter: 10 loss: -3.1085 fid: 0.9241
iter: 20 loss: -3.3375 fid: 0.9799
iter: 30 loss: -3.3692 fid: 0.9897
iter: 40 loss: -3.3990 fid: 0.9929
iter: 50 loss: -3.4133 fid: 0.9959

训练后的电路：
--Ry(6.262)----*--------------X----Ry(0.747)--
               |              |               
--Ry(4.710)----X----*---------|----Ry(6.253)--
                    |         |               
--Ry(-0.01)---------X----*----|----Ry(-0.03)--
                         |    |               
--Ry(-0.00)--------------X----*----Ry(6.312)--
{'fraction_non_alphanumeric': 0.16020313942751616, 'fraction_numerical': 0.03154816866728224, 'mean_word_length': 3.1901998710509347, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '73662', 'license': 'Apache-2.0', 'n_tokens_mistral': 3724, 'n_tokens_neox': 3922, 'n_words': 483, 'path': 'tutorial/quantum_simulation/GibbsState_CN.ipynb', 'repo_name': 'imppresser/Quantum-1', 'size': '6498'}