如何利用 MindQuantum 中自定义的量子门,实现对多个哈密顿量求期望值和梯度?

发布于:2022-12-22 ⋅ 阅读:(394) ⋅ 点赞:(0)

如何利用 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 后查看

网站公告

今日签到

点亮在社区的每一天
去签到