云韬量子:量子-经典混合计算在量子化学中的应用与实践
量子-经典混合计算 整理: Wang, 校对:Yoking
“if you want to make a simulation of nature, you’d better make it quantum mechanical".
-- Feynman (1981)
近年来,量子计算领域不断取得突破性进展,尤其是谷歌9月宣称实现了量子霸权(Quantum supremacy),对特定的任务,在量子芯片上展示了相对传统计算机的巨大优势。通用量子计算机(Universal quantum computer)被认为可以提供远超传统计算机的运算能力。然而,如同所有诗和远方都伴随着面包和牛奶的现实问题,近期可用的量子芯片是含有噪音、无纠错的中等规模(<100 个量子比特)芯片,即处在NISQ (Noisy Intermediate-Scale Quantum) 时代。当前的任务之一就是如何充分发挥NISQ时代量子硬件的能力,有效地解决一些有价值的问题,从而展现具有实际意义的量子优势。
量子化学求解分子的基态能等性质,对药物研发等具有重大意义。在量子计算的众多应用中,量子化学被认为是可以在近期取得量子优势的领域之一。由于计算量指数墙的限制,用传统计算机模拟化学分子是一项非常困难的工作。其中,与其他量子化学算法(例如Quantum phase estimation)相比,变分量子本征求解(Variational Quantum Eigensolver, VQE) 采用量子-经典混合计算架构,其中量子计算部分可在较短时间内进行,减少退相干的影响,从而有利于在近期的量子硬件上实施。
所谓量子-经典混合的计算架构,通常是指在一个系统中,同时包含了量子计算机和经典的CPU/GPU计算部分。利用量子计算机芯片来制备相应量子态并测量,再通过经典计算机算法来分析测量结果并优化量子计算机的参数等。更普遍来讲,可以设计算法让量子计算部分与经典计算部分传递信息,合作来完成计算任务。通过这种量子-经典混合架构,可以充分发挥量子计算的优势,同时借用成熟的经典计算方案来弥补早期量子芯片的噪声、退相干等问题。
在这篇文章中,笔者通过简单的示例,来阐述量子经典混合计算的基本思想,用于优化求解量子化学问题。基于HiQ/ProjectQ和Openfermion框架的所有代码,可以参考Github链接[1]. 在文章最后,还会提到我和合作者最近在量子化学中的一个很有意思的工作,借鉴了蛇的运动特点,设计了一种量子-经典混合算法,来集体优化不同键长的分子的基态问题。希望对大家有启发,借鉴不同领域的想法,更巧妙地设计经典算法的部分去挖掘近期量子计算的潜能。
举例
在量子化学的计算中,我们通常需要根据体系的哈密顿量的具体形式,来求解此哈密顿量基态能量与基态波函数。变分量子本征求解 (VQE) 通过制备带有参数的试探波函数(Ansatz),通过测量体系哈密顿量在该波函数下面的平均值,最后使用经典优化算法来最小化这个平均值,从而确定波函数相关参数。根据基本的原理:
通过对参数变分从而最小化哈密顿量的平均值,同时得到的试探波函数就近似对应着系统的基态波函数。
下面我们通过一个简单例子来演示VQE的基本思想和算法流程。首先我们需要求解的单比特哈密顿量为:
使用HiQ/ProjectQ框架来模拟量子线路,并定义系统哈密顿量:
from projectq.ops import All, Measure, QubitOperator, TimeEvolution
from projectq.ops import CNOT, H, Rz, Rx, Ry, X, Z, Y
import matplotlib.pyplot as plt
from scipy.optimize import minimize_scalar, minimize
import numpy as np
# 定义哈密顿量
hamil = 0.5 * QubitOperator("X0") + 0.7 * QubitOperator("Y0")
np.linalg.eigh(hamil_matrix)
(array([-0.86023253, 0.86023253])
eng = projectq.MainEngine()
qubits = eng.allocate_qureg(1)
# 定义试探波函数
H | qubits[0]
Rz(theta[0]) | qubits[0]
eng.flush()
energy = eng.backend.get_expectation_value(hamiltonian, qubits)
All(Measure) | qubits
return energy
minimum.fun
fun: -0.8602325267042619
eng = projectq.MainEngine()
qubits = eng.allocate_qureg(1)
# 定义新的试探波函数
Z | qubits[0]
Rx(theta[0]) | qubits[0]
eng.flush()
energy = eng.backend.get_expectation_value(hamiltonian, qubits)
All(Measure) | qubits
return energy
minimum.fun
-0.6999999999999997
2、上一步的哈密顿量需要进一步表示成可以用量子芯片直接测量的形式。通常可以使用Bravyi-Kiteav、Jordan-Wigne或者Parity变换将产生湮灭算符转换为qubit泡利算符。对于LiH分子,在STO-6G基经过BK变换的qubit哈密顿量涉及12个qubit。通过考虑有效的电子轨道等近似,LiH分子的哈密顿量可以用三个qubit的泡利算符有效表示为:
代码演示
basis = 'sto-6g'
charge = 0
multiplicity = 1
# Single point at equilibrium for testing
spacings = [1.6]
# Set run options
run_scf = 1
run_mp2 = 1
run_cisd = 1
run_ccsd = 1
run_fci = 1
verbose = 1
# Run Diatomic Curve
for spacing in spacings:
description = "{}".format(spacing)
geometry = [[element_names[0], [0, 0, 0]],
[element_names[1], [0, 0, spacing]]]
molecule = MolecularData(geometry,
basis,
multiplicity,
charge,
description)
molecule = run_pyscf(molecule,
run_scf=run_scf,
run_mp2=run_mp2,
run_cisd=run_cisd,
run_ccsd=run_ccsd,
run_fci=run_fci,
verbose=verbose)
molecule.save()
molecular_hamiltonian = molecule.get_molecular_hamiltonian()
# Map operator to fermions and qubits.
fermion_hamiltonian = get_fermion_operator(molecular_hamiltonian)
qubit_hamiltonian = bravyi_kitaev(fermion_hamiltonian)
qubit_hamiltonian.compress()
def variational_quantum_eigensolver(theta, hamiltonian):
"""
Args:
theta (float): variational parameter for ansatz wavefunction
hamiltonian (QubitOperator): Hamiltonian of the system
Returns:
energy of the wavefunction for parameter theta
"""
# Create a ProjectQ compiler with a simulator as a backend
eng = projectq.MainEngine()
# Allocate 3 qubits in state |000>
wf = eng.allocate_qureg(3)
# Initialize the Hartree Fock state |111>
X | wf[0]
X | wf[1]
X | wf[2]
# UCC-1
Rx(-np.pi/2) | wf[0]
Ry(np.pi/2) | wf[1]
CNOT | (wf[0],wf[1])
Rz(theta[0]) | wf[1]
CNOT | (wf[0],wf[1])
Rx(np.pi/2) | wf[0]
Ry(-np.pi/2) | wf[1]
# UCC-2
Rx(-np.pi/2) | wf[1]
Ry(np.pi/2) | wf[2]
CNOT | (wf[2],wf[1])
Rz(theta[1]) | wf[1]
CNOT | (wf[2],wf[1])
Rx(np.pi/2) | wf[1]
Ry(-np.pi/2) | wf[2]
# flush all gates
eng.flush()
# Calculate the energy.
# The simulator can directly return expectation values, while on a real quantum devices one would have to measure each term of the Hamiltonian.
energy = eng.backend.get_expectation_value(hamiltonian, wf)
All(Measure) | wf
return energy
VQE_energies = []
thetas=[]
for i in range(len(bond_lengths)):
minimum = minimize(lambda theta: variational_quantum_eigensolver(theta,hamiltonian), [0.5,0.5],method='nelder-mead', options={'xtol': 1e-5})
VQE_energies.append(minimum.fun)
thetas.append(minimum.x)
拓展推广
在如上所介绍的传统VQE算法中,对不同原子键长的能量求解是完全独立的,优化时往往会受到局域最小值、测量的统计误差、芯片噪声等因素的影响。为了更有效地利用当前相对昂贵的量子资源,我们同华南师范大学张旦波博士团队合作开发了collective-VQE(cVQE)算法。相对于每次独立的求解VQE,借助计算机视觉领域中的snake算法,我们对不同键长的分子哈密顿量进行协同求解。其中,类似蛇在运动时,身体的相邻部位会相互影响,从而形成整体的运动,VQE的集体优化也会有类似的特点。下图可以看到,不同键长下的波函数变分参数会协同地趋近到目标值,有望节省量子资源:(体系分别为H2, LiH, HeH+)
总结
作者简介
声明:此文出于传递更多信息之目的。若有来源标注错误或侵权,请作者持权属证明与我们联系,我们将及时更正、删除
文章投稿: Sakura@qtumist.com
转载授权:Support@qtumist.com