前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >量子算法与实践--变分量子态对角化算法

量子算法与实践--变分量子态对角化算法

作者头像
量子发烧友
发布2023-02-24 15:57:35
6680
发布2023-02-24 15:57:35
举报
文章被收录于专栏:量子发烧友量子发烧友

概念介绍

变分混合量子—经典算法是近期在量子计算机上有希望实现的一种候选算法。在这些算法中,量子计算机评估一个门序列所耗费的成本与经典的成本评估相比较低,速度上也会更快一些。通过量子计算机评估的门序列信息,最终也可用于经典计算机调整门序列的参数。

在这些变分量子算法中,我们提出这样一种算法——量子态对角化算法(variational quantum state diagonalization, VQSD)。

变分量子态对角算法的目标是对角化一个半正定矩形 ρ,它可以对应一个量子系统的密度矩阵,成分分析(principal component analysis,PCA)中的协方差矩阵。

n-qubits 的密度矩阵可以用一个 2n-qubits 的纯态来表示 Purification:

\rho ={\textstyle \sum_{i}}p_i\left | \psi _i \right \rangle\left \langle \psi_i \right | \longleftarrow \left | \Psi \right \rangle = {\textstyle \sum_{i}}\sqrt{p_i}\left | \psi_i \right \rangle \left | \phi _i \right \rangle

Choi-Jamiołkowski isomorphism:

\rho = {\textstyle \sum_{i}} p_i \left | \psi_i \right \rangle \left \langle \psi_i \right | \leftrightarrow \left | \Psi \right \rangle = \frac{1}{c} {\textstyle \sum_{i}} p_i \left | \psi_i \right \rangle \left | \psi_i \right \rangle ,c= {\textstyle \sum_{i}} {\textstyle p_{i}^{2}}

VQSD 的损失函数可以定义为当前密度矩阵距离被完全对角化还有多远,比如Hilbert-Schmidt distance:

C(\theta )= {\textstyle d_{HS}^{2}}(\rho ,\mathcal{Z}(\rho ) ) =T_r \left | \rho (\theta ) - \mathcal{Z}(\rho (\theta )) \right |^2

其中 , 是非对角元置零。即对 非对角元的模方求和。而状态对角化在凝聚态物理学(如纠缠光谱学)以及机器学习(如主成分分析)中都有应用。

工具搭建

在本文中,我们将使用 Paddle Quantum 来完成训练量子神经网络来实现量子态的对角化的操作。

首先是环境搭建,我们需要通过下面几行代码引入操作中必要的 library 和 package。

代码示例如下:

代码语言:javascript
复制
import numpy
from numpy import diag
from numpy import pi as PI
import scipy
import scipy.stats
import paddle
from paddle import matmul, trace
import paddle_quantum
from paddle_quantum import intrinsic
from paddle_quantum.ansatz import Circuit
from paddle_quantum.linalg import dagger

示例

量子态对角化算法的目标是输出一个量子态的本征谱,也就是它所有的本征值。求解量子态的本征值在量子计算中有着诸多应用,比如可以用于计算保真度和冯诺依曼熵,也可以用于主成分分析。

在实际情况中,量子态通常是一个混合态,具体表示如下:

ρ_{mixed}=∑_i P_i |ψ_i⟩ ⟨ψ_i|

这里举一个简单的例子。我们可以考虑一个 2 量子位的量子态,它的本征谱为 (0.5,0.3,0.1,0.1),我们可以先通过随机作用一个酉矩阵来生成具有这样本征谱的随机量子态。具体代码如下:

代码语言:javascript
复制
scipy.random.seed(13)                  # 固定随机种子,方便复现结果
V = scipy.stats.unitary_group.rvs(4)   # 随机生成一个酉矩阵
D = diag([0.5, 0.3, 0.1, 0.1])         # 输入目标态 rho 的谱
V_H = V.conj().T 
rho = V @ D @ V_H                      # 通过逆向的谱分解生成 rho
print(numpy.around(rho, 4))            # 打印量子态 rho

输出结果为:

代码语言:javascript
复制
[[ 0.2569+0.j     -0.012 +0.0435j -0.0492-0.0055j -0.0548+0.0682j]
 [-0.012 -0.0435j  0.2959-0.j      0.1061-0.0713j -0.0392-0.0971j]
 [-0.0492+0.0055j  0.1061+0.0713j  0.2145-0.j      0.0294-0.1132j]
 [-0.0548-0.0682j -0.0392+0.0971j  0.0294+0.1132j  0.2327+0.j    ]]

搭建量子神经网络

接下来,我们将通过训练量子神经网络的参数化量子电路(QNN)来完成量子态的本征谱。同上,我们设计一个预设的 2 量子位量子电路。同时我们预设修改一些这个参数化电路的某些参数,比如宽度为 2 量子位。然后初始化其中的变量参数,θ 代表我们量子神经网络中的参数组成的向量。

具体示例代码如下:

代码语言:javascript
复制
N = 2            # 量子神经网络的宽度
SEED = 14        # 固定随机种子
THETA_SIZE = 15  # 量子神经网络中参数的数量

def U_theta(N: int) -> Circuit:
    """
    Quantum Neural Network
    """
    
    # 按照量子比特数量/网络宽度初始化量子神经网络
    cir = Circuit(N)
    # 调用内置的量子神经网络模板
    cir.universal_two_qubits([0, 1])
    # 返回量子神经网络的电路
    return cir

配置训练模型——损失函数

经过上述步骤后,现在我们已经完成了数据和量子神经网络的架构,接下来我们将进一步定义训练参数、模型以及损失函数。具体步骤如下:

  1. 通过作用量子神经网络 在量子态 后得到的量子态,我们记为 ,同时设定损失函数为 用来标记的量子态 的内积。
  2. 设定损失函数的具体公式为 σ

具体步骤如下:

代码语言:javascript
复制
# 输入用来标记的量子态sigma
sigma = diag([0.1, 0.2, 0.3, 0.4])

class Net(paddle.nn.Layer):
    """
    Construct the model net
    """

    def __init__(self, rho, sigma):
        super(Net, self).__init__()
        
        # 将 numpy.ndarray 转换成 Paddle 中支持的 Tensor
        complex_dtype = paddle_quantum.get_dtype()
        self.rho = paddle.cast(paddle.to_tensor(rho), complex_dtype)
        self.sigma = paddle.cast(paddle.to_tensor(sigma), complex_dtype)

        # 施加量子神经网络
        self.cir = U_theta(N)                                  

    # 定义损失函数和前向传播机制
    def forward(self, N):
            
        # rho_tilde 是将 U 作用在 rho 后得到的量子态 U*rho*U^dagger 
        U = self.cir.unitary_matrix()
        rho_tilde = matmul(matmul(U, self.rho), dagger(U))

        # 计算损失函数
        loss = trace(matmul(self.sigma, rho_tilde))

        return paddle.real(loss), rho_tilde, self.cir

配置训练模型——模型参数

完成上述配置后,我们接下来的工作基本就是进行训练了。但在进行量子神经网络的训练之前,还需要我们进行一些训练中的超参数设置,主要是学习速率 (learning rate, LR) 和迭代次数 (iteration, ITR) 的训练。

不同数值对训练结果有不同的影响,这两项数值可以自由进行调整。那在这里我们先将学习速率设定为 0.1,迭代次数为 50 次。

代码语言:javascript
复制
ITR = 50  # 设置训练的总的迭代次数
LR = 0.1  # 设置学习速率

进行训练

当关于训练模型的所有参数都完成设置后,我们可以正式对模型进行量子神经网络的训练了。首先我们需将数据转化为 Paddle 中的张量,接着将训练结果在程序中依次输出。

具体操作步骤如下:

代码语言:javascript
复制
paddle.seed(SEED)

# 确定网络的参数维度
net = Net(rho=rho, sigma=sigma)

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

# 优化循环
for itr in range(ITR):

    # 前向传播计算损失函数并返回估计的能谱
    loss, rho_tilde, cir = net(N)
    rho_tilde_np = rho_tilde.numpy()

    # 反向传播极小化损失函数
    loss.backward()
    opt.minimize(loss)
    opt.clear_grad()

    # 打印训练结果
    if itr % 10 == 0:
        print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])

最终输出结果为:

代码语言:javascript
复制
iter: 0 loss: 0.2494
iter: 10 loss: 0.1959
iter: 20 loss: 0.1843
iter: 30 loss: 0.1816
iter: 40 loss: 0.1805   
                                                   

结果

依据上面训练所得到的结果可以看出,只通过大约 50 次的迭代,我们就比较顺利的完成了变分量子态的对角化。我们可以通过输出 θρθ 的结果来验证谱分解的效果。通过对比我们可以看出,它的对角线与目标谱非常接近,说明我们的训练是成功的。

代码语言:javascript
复制
print("The estimated spectrum is:", numpy.real(numpy.diag(rho_tilde_np)))
print("The target spectrum is:", numpy.diag(D))
代码语言:javascript
复制
The estimated spectrum is: [0.49938068 0.29916352 0.10103808 0.10041767]
The target spectrum is: [0.5 0.3 0.1 0.1]
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 量子发烧友 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概念介绍
  • 工具搭建
  • 示例
  • 搭建量子神经网络
  • 配置训练模型——损失函数
  • 配置训练模型——模型参数
  • 进行训练
  • 结果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档