本章内容是用PyTorch与TN_tutorial 的 Library 搭建VQC(量子变分线路)实例
最终解释权归首都师范大学的冉仕举老师所有:
https://space.bilibili.com/401005433
* 演化门和多体门:
* 一个qbit,演化门能让它一直单独地演化下去,与其它qbits不发生任何纠缠
* 目前我们能做的工作仅仅是参数化单体门,至于多体纠缠部分用非参数化门实现
* 为了囊括更多多体纠缠门,我们换个编码思路:可以考虑在两个qbits之间建立优化参数矩阵
* 理论细节可以参照:https://journals.aps.org/pra/abstract/10.1103/PhysRevA.104.042601
* 何为隐门(Latent Gates)
* 首先作为幺正演化算符的G(m)其幺正性并不容易初始化,以及优化更新过程中一路保持
* 于是先定义V(m),整体参数作为2**num_entangled x 2**num_entangled 规模的张量,
* 演化结果、保真度用G(m), 更新与优化用V(m),对应以上图示的 和
* 编码样例与思路:
* 准备量子态,门演化的实例,依然是Tensor_pure_state,act_single_gate:
num_qubits, num_gates = 3, 4
psi_target = tc.randn((2**num_qubits, ), dtype=tc.complex128)
psi_target /= psi_target.norm()
* 存储隐门,开一个4个一组的list:
V = [tc.randn((4, 4), dtype=tc.complex128,
requires_grad=True) for _ in range(num_gates)]
optimizer = Adam(V, lr=lr)
* 不打断反向传播链,V -- U,扔掉奇异谱:
for t in range(it_time):
# 从隐门生成幺正门
U = list()
for x in V:
P, S, Q = tc.linalg.svd(x)
U.append(P.mm(Q))
# 建立初态|000>
psi = qs.state_all_up(n_qubit=3, d=2)
psi = qs.TensorPureState(psi)
# 作用各个量子门
psi.act_single_gate(U[0], [0, 1])
psi.act_single_gate(U[1], [1, 2])
psi.act_single_gate(U[2], [0, 1])
psi.act_single_gate(U[3], [1, 2])
* 还是把 V 整组作为参数进行梯度下降,非保真度的 计算如此:
loss = 1 - psi.tensor.conj().flatten().dot(
psi_target).norm()
loss.backward()
optimizer.step()
optimizer.zero_grad()
* 完整代码:
import torch as tc
import matplotlib.pylab as plt
import LibraryQ.QuantumState as qs
from torch.optim import Adam
lr, it_time = 1e-3, 2048 # 初始学习率与迭代总次数
print('随机生成目标态')
num_qubits, num_gates = 3, 4
psi_target = tc.randn((2**num_qubits, ), dtype=tc.complex128)
psi_target /= psi_target.norm()
print('初始化4个隐门并建立优化器')
V = [tc.randn((4, 4), dtype=tc.complex128,
requires_grad=True) for _ in range(num_gates)]
optimizer = Adam(V, lr=lr)
loss_rec = tc.zeros(it_time, )
print('开始优化')
for t in range(it_time):
# 从隐门生成幺正门
U = list()
for x in V:
P, S, Q = tc.linalg.svd(x)
U.append(P.mm(Q))
# 建立初态|000>
psi = qs.state_all_up(n_qubit=3, d=2)
psi = qs.TensorPureState(psi)
# 作用各个量子门
psi.act_single_gate(U[0], [0, 1])
psi.act_single_gate(U[1], [1, 2])
psi.act_single_gate(U[2], [0, 1])
psi.act_single_gate(U[3], [1, 2])
loss = 1 - psi.tensor.conj().flatten().dot(
psi_target).norm()
loss.backward()
optimizer.step()
optimizer.zero_grad()
loss_rec[t] = loss.item()
if t % 20 == 19:
print('第%d次迭代,loss = %g' % (t, loss.item()))
plt.plot(loss_rec)
plt.xlabel('iteration time')
plt.ylabel('loss')
plt.show()
*效果对比:
目标态:(两个子程序生成的一个给两者共享)
psi_target = tc.tensor([-0.2682+0.0988j, -0.0066-0.0570j, -0.2828-0.0667j, 0.0020-0.4100j,
0.0517+0.1907j, 0.0315+0.3045j, 0.6354+0.1356j, -0.2015-0.2588j],
dtype=tc.complex128)
基于量子门实体线路的参数化:
基于隐门的参数化:
可以看到隐门在以更加‘灵活’的调整自由度来更新参数的,ADQC比经典更新得也就快得多了。值得一提的是,量子线路虽然可以以更加灵活的自由度对问题的解进行搜索,然而这也可能导致搜索平面异常,出现‘贫瘠高原’ 的状况。