如何利用 MindQuantum 中自定义的量子门,实现对多个哈密顿量求期望值和梯度?
由于迄今的 MindQuantum 0.7.0 及之前版本都是不支持这个功能的(一旦使用,python 会自动重启内核)真是遗憾,希望官方能早日完成改进。本博文将展示如何基于当前版本 MindQuantum 采用差分法求自定义量子门对多个哈密顿量的期望值和梯度。
问题描述:MindQuantum 当前版本的一点缺陷
先采用 MindQuantum 自带的基本门 RX(theta)
搭建线路。这种方法下,无论是使用单个还是多个哈密顿量都是没问题的。
import numpy as np
from mindquantum import *
circ = Circuit()
circ += RX('a').on(0)
circ.as_ansatz()
sim = Simulator('projectq', circ.n_qubits)
# 先对单个哈密顿量进行计算
ham_0 = [Hamiltonian(QubitOperator('Z0'))] # 单个哈密顿量
grad_ops_0 = sim.get_expectation_with_grad(ham_0, circ)
params_0 = np.array([1.2], dtype=float) # 参数
f, g = grad_ops_0(params_0) # 求解期望值和梯度
print('单个哈密顿情况下:')
print('期望值:', f.real.squeeze())
print('梯度:', g.real.squeeze())
# 对多个哈密顿量进行计算
ham_1 = [Hamiltonian(QubitOperator('Z0')), Hamiltonian(QubitOperator('X0'))] # 多个哈密顿量
grad_ops_1 = sim.get_expectation_with_grad(ham_1, circ)
params_1 = np.array([1.2], dtype=float) # 参数
f, g = grad_ops_1(params_1) # 求解期望值和梯度
print('\n多个哈密顿情况下:')
print('期望值:', f.real.squeeze())
print('梯度: ', g.real.squeeze())
单个哈密顿情况下:
期望值: 0.36235775447667357
梯度: -0.9320390859672264
多个哈密顿情况下:
期望值: [0.36235775 0. ]
梯度: [-0.93203909 0. ]
采用 gene_univ_parameterized_gate
方法自定义量子门。这里所定义的其实就是 RX(theta)
门。这种方法下,使用目前版本的 MindQuantum 只能计算单个哈密顿量的情况,多个哈密顿量的话会中断内核。
import numpy as np
from mindquantum import *
def matrix(theta):
return np.array([[np.cos(theta / 2), -1j * np.sin(theta / 2)],
[-1j * np.sin(theta / 2), np.cos(theta / 2)]])
def diff_matrix(theta):
return 0.5 * np.array([[-np.sin(theta / 2), -1j * np.cos(theta / 2)],
[-1j * np.cos(theta / 2), -np.sin(theta / 2)]])
test_gate = gene_univ_parameterized_gate('gete', matrix, diff_matrix) # 自定义量子门
circ = Circuit()
circ += test_gate('a').on(0)
circ.as_ansatz()
sim = Simulator('projectq', circ.n_qubits)
# 先对单个哈密顿量进行计算
ham_0 = [Hamiltonian(QubitOperator('Z0'))] # 单个哈密顿量
grad_ops_0 = sim.get_expectation_with_grad(ham_0, circ)
params_0 = np.array([1.2], dtype=float) # 参数
f, g = grad_ops_0(params_0) # 求解期望值和梯度
print('单个哈密顿情况下:')
print('期望值:', f.real.squeeze())
print('梯度:', g.real.squeeze())
单个哈密顿情况下:
期望值: 0.36235775447667357
梯度: -0.9320390859672264
对多个哈密顿量进行计算就会中断内核,所以这里也就没有输出了。
ham_1 = [Hamiltonian(QubitOperator('Z0')), Hamiltonian(QubitOperator('X0'))] # 多个哈密顿量
grad_ops_1 = sim.get_expectation_with_grad(ham_1, circ)
params_1 = np.array([1.2], dtype=float) # 参数
f, g = grad_ops_1(params_1) # 求解期望值和梯度
print('\n多个哈密顿情况下:')
print('期望值:', f.real.squeeze())
print('梯度: ', g.real.squeeze())
下面基于 MindQuantum 和 差分法 求期望值和梯度。先介绍一下差分法。
求解梯度的一阶差分公式为:
g r a d = f ′ ( x i ) = f ( x i + η ) − f ( x i − η ) 2 η . grad=f'(x_i)=\frac{f(x_i+\eta)-f(x_i-\eta)}{2\eta}. grad=f′(xi)=2ηf(xi+η)−f(xi−η).
其中, η \eta η 是一个很小的量,比如 0.0001.
下面我们用代码来实现它。
我们用自定义的门构成线路 circ
,同时也用基础门做一个相同的线路 circ_1
作为对比。
import copy
circ = Circuit()
circ += RX(1).on(0)
circ += test_gate('a').on(0)
circ += test_gate('b').on(0)
circ += test_gate('c').on(0)
circ.as_ansatz()
circ_1 = Circuit()
circ_1 += RX(1).on(0)
circ_1 += RX('a').on(0)
circ_1 += RX('b').on(0)
circ_1 += RX('c').on(0)
circ_1.as_ansatz
我们自己定义一个函数 get_expectation_with_grad
,这也是本文最核心的内容。
def get_expectation_with_grad(hams, circ, params):
h = 1e-4
grad = []
sim.reset()
sim.apply_circuit(circ, params)
exceptation = [sim.get_expectation(ham).real for ham in hams]
for i in range(params.size):
params_p, params_n = copy.deepcopy(params), copy.deepcopy(params)
params_p[i] += h
params_n[i] -= h
sim.reset()
sim.apply_circuit(circ, params_p)
g_p = [sim.get_expectation(ham) for ham in hams]
sim.reset()
sim.apply_circuit(circ, params_n)
g_n = [sim.get_expectation(ham) for ham in hams]
grad.append([(p.real - n.real)/(2*h) for p, n in zip(g_p, g_n)])
sim.reset()
return exceptation, np.array(grad).T
下面的测试说明,我们自定义的程序和 MindQuantum 该给出结果是相同的。
params = np.array([1.2, 1.1, -3.1],dtype=float)
sim = Simulator('projectq', 1)
ham_1 = [Hamiltonian(QubitOperator('Z0')), Hamiltonian(QubitOperator('X0'))]
f_0, grad_0 = get_expectation_with_grad(ham_1, circ, params)
print('自定义函数求得的结果:')
print('期望值为:', f.squeeze().real)
print('梯度为: ', grad.squeeze().real)
sim.reset()
grad_ops = sim.get_expectation_with_grad(ham_1, circ_1)
f_1, grad_1 = grad_ops(params)
print('\nMindQuantum 应该输出的为:')
print('期望值为:', f.squeeze().real)
print('梯度为: ', grad.squeeze().real)
print('\n期望是否一样:', np.allclose(np.abs(f_0 - f_1), 0))
print('梯度是否一样:', np.allclose(np.abs(grad_0 - grad_1), 0))
自定义函数求得的结果:
期望值为: [0.98006658 0. ]
梯度为: [[-0.19866933 -0.19866933 -0.19866933]
[ 0. 0. 0. ]]
MindQuantum 应该输出的为:
期望值为: [0.98006658 0. ]
梯度为: [[-0.19866933 -0.19866933 -0.19866933]
[ 0. 0. 0. ]]
期望是否一样: True
梯度是否一样: True
本文含有隐藏内容,请 开通VIP 后查看