变分混合量子—经典算法是近期在量子计算机上有希望实现的一种候选算法。在这些算法中,量子计算机评估一个门序列所耗费的成本与经典的成本评估相比较低,速度上也会更快一些。通过量子计算机评估的门序列信息,最终也可用于经典计算机调整门序列的参数。
在这些变分量子算法中,我们提出这样一种算法——量子态对角化算法(variational quantum state diagonalization, VQSD)。
变分量子态对角算法的目标是对角化一个半正定矩形 ρ,它可以对应一个量子系统的密度矩阵,成分分析(principal component analysis,PCA)中的协方差矩阵。
n-qubits 的密度矩阵可以用一个 2n-qubits 的纯态来表示 Purification:
Choi-Jamiołkowski isomorphism:
VQSD 的损失函数可以定义为当前密度矩阵距离被完全对角化还有多远,比如Hilbert-Schmidt distance:
其中 , 是非对角元置零。即对 非对角元的模方求和。而状态对角化在凝聚态物理学(如纠缠光谱学)以及机器学习(如主成分分析)中都有应用。
在本文中,我们将使用 Paddle Quantum 来完成训练量子神经网络来实现量子态的对角化的操作。
首先是环境搭建,我们需要通过下面几行代码引入操作中必要的 library 和 package。
代码示例如下:
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
量子态对角化算法的目标是输出一个量子态的本征谱,也就是它所有的本征值。求解量子态的本征值在量子计算中有着诸多应用,比如可以用于计算保真度和冯诺依曼熵,也可以用于主成分分析。
在实际情况中,量子态通常是一个混合态,具体表示如下:
这里举一个简单的例子。我们可以考虑一个 2 量子位的量子态,它的本征谱为 (0.5,0.3,0.1,0.1),我们可以先通过随机作用一个酉矩阵来生成具有这样本征谱的随机量子态。具体代码如下:
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
输出结果为:
[[ 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 量子位。然后初始化其中的变量参数,θ 代表我们量子神经网络中的参数组成的向量。
具体示例代码如下:
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
经过上述步骤后,现在我们已经完成了数据和量子神经网络的架构,接下来我们将进一步定义训练参数、模型以及损失函数。具体步骤如下:
具体步骤如下:
# 输入用来标记的量子态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 次。
ITR = 50 # 设置训练的总的迭代次数
LR = 0.1 # 设置学习速率
当关于训练模型的所有参数都完成设置后,我们可以正式对模型进行量子神经网络的训练了。首先我们需将数据转化为 Paddle 中的张量,接着将训练结果在程序中依次输出。
具体操作步骤如下:
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])
最终输出结果为:
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 次的迭代,我们就比较顺利的完成了变分量子态的对角化。我们可以通过输出 θρθ 的结果来验证谱分解的效果。通过对比我们可以看出,它的对角线与目标谱非常接近,说明我们的训练是成功的。
print("The estimated spectrum is:", numpy.real(numpy.diag(rho_tilde_np)))
print("The target spectrum is:", numpy.diag(D))
The estimated spectrum is: [0.49938068 0.29916352 0.10103808 0.10041767]
The target spectrum is: [0.5 0.3 0.1 0.1]