1. 典型的量子算法
量子算法是量子计算机的必要软件支撑,同时量子算法的研究也是推动量子计算发展的强大动力。以下将对各个发展阶段的典型量子算法进行比较分析。
其中,探索阶段选择的量子算法是Simon算法;质变阶段选择的量子算法有两个,分别是Shor算法和Grover算法(量子算法中最著名的算法);繁荣发展阶段选择的量子算法是VQE变分量子特征值求解算法;AI探索阶段选择的量子算法是Google提出的Tensorflow Quantum(TFQ)框架。
1.1 Shor算法
Simon算法是由丹尼尔·西蒙20年前提出,认为这种算法能够挖掘量子计算机的加速潜力。Simon算法的目的,是为了解决量子黑箱问题,即将执行计算任务的一段程序或者一个公式看作黑箱,看黑箱是否对每一个可能的输入给出一个唯一的输出。
重要性:实现了从指数级复杂度到多项式加速。
主要应用:主要应用于硬件或软件条件受限(例如:芯片面积要求小、微处理器、低功耗等),同时对安全有一定需求的低端设备。
为了适应不同的场合,Simon提供了不同的方案
图:Simon密码族
图:Simon轮函数结构图
其中, block size : 明文块大小,比特位;
key size : 初始密钥大小,比特位;
word size : "字"大小,比特位;
key words : 初始密钥包含"字"的个数;
const seq : 计算轮密钥应该使用的z的值;
rounds : 加解密的轮数。
以下是Simon算法流程:(以加解密轮函数和密钥编排算法为例)
轮加密
每一轮的操作如上图“Simon轮函数结构图”。明文被分成两个"字",每个"字"的二进制位数都为n(即word size),x_(i+1)和x_i分别表示高位部分和低位部分(个人认为,这个没有特别要求,x_(i+1)也可以表示低位、x_i表示高位部分,只要加解密按照同样的顺序即可。为了叙述统一,本文按照x_(i+1)表示高位、x_i表示低位)。
每轮的加密主要涉及到3种操作,分别是异或、按位与和循环左移(如果j是负数则表示循环右移)。每轮加解密的过程用公式表示,其中x对应x_(i+1)、y对应x_i、k为轮密钥。
Simon运算符号:
Simon轮加解密公式:
在C++实现中,按位异或和与都有直接的操作符,对于循环移位可以按照如下方法实现。将x循环左移i(i>=0)位,假设x对应的二进制位数为n,则可以表示为: (x<>(n-i))。当然,x应该是无符号的数,不然会出错。
/
加密后的低32位是明文的高32位
/
tempCipherLower = plainText[];
tempCipherHigher = plainText[] ^ keys[i] ^
( ((plainText[]<<)|(plainText[]>>(SIMON_WORD_SIZE-))) & ((plainText[]<<)|(plainText[]>>(SIMON_WORD_SIZE-))) ) ^
((plainText[]<<)|(plainText[]>>(SIMON_WORD_SIZE-)));
/
重新将加密的结果复制到plainText中
/
plainText[] = tempCipherHigher;
plainText[] = tempCipherLower;
密钥编排
密钥编排算法如下,其中m表示的是原始密钥中"字"的个数。
c为一个常数,它的二进制位数为n,最低两位为0,其余高位为1。
z是一个常数数组,值见下图,在每种情况下z的取值都是固定的,每轮加解密时只取一个比特位参与运算。
ki、ki+1、ki+2等都是轮密钥。
I表示不进行移位。
C++代码实现如下(只包含block size为64,key size为96和128的两种情况):
/
Simon:计算密钥,字大小为32
inputKey:初始的密钥
keys:计算后得到的每轮密钥
/
void setSimonKeys32 ( unsigned int * inputKey, unsigned int * keys ) {
/
算法中的常数c,大小为2^n - 4,其中n是字的长度,即SIMON_WORD_SIZE
转化为二进制,即最低两位为0,其它位全为1
/
unsigned int c = 0xfffffffc;
int i;
; i < SIMON_KEY_WORDS; i++ ) {
keys[i] = inputKey[i];
}
/*
求解后面轮的密钥
先求其它的异或,最后求Zji,如果为1则对最低位进行修改,否则不变
/
) {
; i < SIMON_ROUNDS-SIMON_KEY_WORDS; i++ ) {
keys[i+SIMON_KEY_WORDS] = c ^ keys[i] ^
((keys[i+]>>) | (keys[i+]<<(SIMON_WORD_SIZE-))) ^
((keys[i+]>>) | (keys[i+]<<(SIMON_WORD_SIZE-)));
// SIMON_WORD_SIZE为32时,无论SIMON_KEY_WORDS为3还是4,周期都是62
] == ) {
keys[i+SIMON_KEY_WORDS] ^= 0x1;
}
}
} ) {
// int cycle = (SIMON_SEQUENCE_NUMBER == 0 || SIMON_SEQUENCE_NUMBER == 1)?31:62;
unsigned int temp = 0x00000000;
; i < SIMON_ROUNDS-SIMON_KEY_WORDS; i++ ) {
temp = ((keys[i+]>>) | (keys[i+]<<(SIMON_WORD_SIZE-))) ^ keys[i+];
keys[i+SIMON_KEY_WORDS] = c ^ keys[i] ^ temp ^ ((temp>>) | (temp<<(SIMON_WORD_SIZE-)));
] == ) {
keys[i+SIMON_KEY_WORDS] ^= 0x00000001;
}
}
}
}
参考:
[1] Beaulieu R, Shors D, Smith J, et al. The SIMON and SPECK Families of Lightweight Block Ciphers[J]. IACR Cryptology ePrint Archive, 2013, 2013: 404.
[2] bbsmax网站《Simon简介》,原文链接:https://www.bbsmax.com/A/pRdBoA69zn/
1.2 Shor算法
shor算法也称秀尔算法,以数学家彼得·秀尔命名,是一个在1994年提出的一种大数质因子分解的量子多项式算法。Shor量子计算将NP问题变为了P问题,和用数论中的一些定理将大数因子分解转化为求某个函数的周期,由于在量子环境下可以提高效率实现量子傅立叶变换,从而可以对大数质因子进行化简。
在一个量子计算机上面,要分解整数N,shor算法的运作需要多项式时间,质因数分解问题可以使用量子计算机以多项式时间解出,因此在复杂度类BQP里面,比起传统已知最快的因数分解算法(普通数域筛选法)还要快了一个指数的差异。
重要性:Shor算法利用了量子力学的多种特性显示出在RSA加密技术破解方面的优势。它代表使用量子计算机的话可以用来破解已被广泛使用的公开密钥加密方法(RSA加密算法)。
主要应用: 在量子密码学、量子通信方面、shor算法后续研究、模拟实现的参考具有一定辅助作用。
大数质因子分解问题为:N为已知大奇数,N = pq,求 p和q。
(1)随机抽取正整数y,y < N,且与N互质,即gcd(y,N)=1 。
(2)定义f(x)= y^xmod < N,可看出f(x)是一个周期函数,若周期是r,则:
故:
(3)求p和q。
用辗转相除法求y^(r/2)+1 和N的最大公约数,设为p。
上面各步中的主要计算是辗转相除、计算f(x)和求f(x)的周期。辗转相除的时间复杂度为O(n^2)。计算f(x)时间复杂度为O(n^2 (lgn)(lglgn))。求f(x)的周期需要进行傅立叶变换,量子傅立叶变换的时间复杂度为O(lgn),所以,shor量子算法的时间复杂度为O(n^2 (lgn)(lglgn))。
Shor算法的关键之处是利用量子傅立叶变换求f(x)的周期。
量子傅立叶变换QFT(Quantum Fourier Transform)的定义:
可以看出QFT是么正变换,QFT可由两种量子门实现,所用的门的数量为m(m+1)/2。这两种门是H门,另一种是2个量子位的相移门,其算符如下:
S_jk是幺正矩阵。
参考:彭卫丰,江南大学信息学院,孙力,江南大学网络教育学院,Shor量子算法的优化及应用研究。
1.3 Grover算法
Grover算法(Quantum Search Algorithm)是量子计算领域的主要算法之一,由Grover于1996年提出的平方根加速的随机数据库量子搜索算法,旨在利用量子计算机进行比经典计算机更快的数据搜索。在数据库足够混乱且没有具体的数据结构限定的条件下,Grover算法可以快速解决从N个未分类的客体中寻找出某个特定个体的问题。除搜索时间远短于经典计算外,其强大之处还在于Grover算法的公式可适用于很多问题,比如:密码学、矩阵和图形问题、优化以及量子机器学习等。
Grover算法搜寻目标对象的逻辑大致为在无序的数据集合中寻找X,首先制备全部量子态的叠加态,然后循环进行操作使得目标态的符号反向(Oracle算符)且态的符号也反向(Grover算符);在执行次操作后,量子态被旋转至目标态;最后测量所得结果概率发现X出现的概率趋近于1,此时即可通过Grover算法找到目标X。一般地,如果想要在N个信息找到对应信息,进行4/pie*√N次操作,进行测量得到的概率趋于1。因此,Grover算法进行无序搜索主要步骤有三个:制备量子态、G迭代、测量。
重要性:Grover算法的重要性,一是因为Grover算法解决的无序数据库搜索问题就是一个很重要的问题;二是因为,Grover量子算法的提出,和Shor质因子分解算法提出一样,给了研究者们用量子算法解决经典算法无法有效解决的问题的希望,极大提高了人们对于量子算法研究的热情;三是,从Grover算法衍生出了一系列利用了幅度放大思想的算法,是现今量子算法研究中的一个重要部分。
Grover算法步骤
Grover算法总体分为三大步骤:制备量子态、标记目标进行相位翻转并放大概率振幅、测量。Grover算法利用量子特性将目标值与其余值进行区分,采用验证是否符合条件的方式而不是线性查找的方式逼近正确答案。
复杂度:Grover搜索算法需要O(√N)次查询,其中N表示搜索空间元素的个数,相较于经典搜索 O(N) 具有多项式量级的加速。
量子线路
为了便于分析,定义两个量子态
“Good”态
“Bad”态
其中 t就是满足x_i=1的个数。
算法步骤如下:
1.设置初始量子态
2.令ε=t/N,应用k=O(1/ε)次如下变换:
3.测量寄存器的状态,并检查测量结果i是否是解。
其中,算法第2步理解如下:
量子态从状态∣U⟩出发,通过不断的“反射+反射”,不断向目标态∣G⟩靠近。而目标态∣G⟩就是满足∣i⟩的叠加态。
QuTrunk Grover算法部分代码示例
QuTrunk基于python提供量子编程API,对量子编程涉及到的基本概念做了代码层面的抽象封装和实现。QuTrunk通过接入启科自主研发的量子计算后端设备QuBox可实现量子算法运行。以下为QuTrunk实现Grover算法部分代码示例:
步骤1:首先在QuIDE中导入随机数模块和QuTrunk中的部分模块
import math
import random
from numpy import pi
from QuTrunk.core.circuit import QCircuit, InitState
from QuTrunk.core.gates import H, X, C, Z
from QuTrunk.core.calculator import Calculator 9. from QuTrunk.core.counter import Counter
步骤2: 调用Oracle门和Diffuser函数,将量子态进行相位翻转和放大(部分代码省略)
def apply_oracle(qr, num_qubits, sol_elem)...
def apply_diffuser(qr, num_qubits)...
步骤3:运行Grover算法,不断进行G迭代直至搜索出目标值
def run_grover():
num_qubits = 15
num_elems = 2 ** num_qubits
num_reps = math.ceil(pi / 4 * math.sqrt(num_elems))
print("num_qubits:", num_qubits, "num_elems:", num_elems, "num_reps:", num_reps)
步骤4:输出运行结果
从结果中可观察到搜索的量子比特数为15Qubit、量子门数为11726个、总的运行时间为10.8659s(其中QuBox运行时间为10.6309s,QuTrunk运行时间仅为0.2350s)。
Counter(quit=15)
qubits = 15
quantum_gates = 11726
total_time = 10.865945100784302
qubox_time = 10.630940914154053
qutrunk_time = 0.23500418663024902
以上Grover算法中生成随机数目标为17560,最终搜索结果概率峰值为0.999986接近于1。在搜索过程中,当此概率出现峰值且第一次下降时即停止搜索,认为已经找到目标值即为17560。
1.4 VQE变分量子特征值求解算法
变分量子本征求解器(variational quantum eigensolver, VQE)指利用经典优化器训练一个含参量子线路,用于求解矩阵本征值和本征矢的算法。VQE 是第一种被提出来的 VQA,目标是寻找一个哈密顿量H的基态和低激发态。下文以基态为例介绍。
对于基态,损失函数就是能量的期望
在经典计算机上我们可以将|ψ(θ)〉表示出来(一个 quantum circuit 直接对应一个 tensor network),然后测出能量,但是它消耗的存储容量随着需要计算的物理系统大小指数增长。
而对于一台量子计算机,我们只需要重复地将|ψ(θ)〉制备出来,测量取平均得到哈密顿量中相加的每一项的期望值。后者消耗的计算资源随需要计算的物理系统大小呈多项式增长,于此体现出相较于纯经典算法的优越性。
以求基态为例,VQE 的整体流程如下:
1.选定一个含参的试探波函数(trial wave function)以及初始参数θ_0;
2.利用量子计算机测量出|ψ(θ)〉的能量期望C(θ)= <ψ(θ)|H|ψ(θ)〉;
3.为不断降低能量,利用经典优化器更新参数θ_0 〖→θ〗_1,返回第 2 步,直至收敛。
以下将通过量桨的量子化学工具包(基于 psi4 和 openfermion)为例,寻找氢分子H2基态能量。
构造电子哈密顿量
import paddle
import paddle_quantum.qchem as qchem
from paddle_quantum.loss import ExpecVal
from paddle_quantum import Hamiltonian
from paddle_quantum.state import zero_state, State
from paddle_quantum.ansatz import Circuit
from paddle_quantum.linalg import dagger
from paddle_quantum import Backend
import os
import matplotlib.pyplot as plt
import numpy
from numpy import pi as PI
from numpy import savez, zeros
# 无视警告
import warnings
warnings.filterwarnings("ignore")
通过量桨的量子化学工具包将分子的哈密顿量提取出来并储存为 paddle quantum 的 Hamiltonian 类
geo = qchem.geometry(structure=[['H', [-0., 0., 0.0]], ['H', [-0., 0., 0.74]]])
# geo = qchem.geometry(file='h2.xyz')
# 将分子信息存储在 molecule 里,包括单体积分(one-body integrations),双体积分(two-body integrations),分子的哈密顿量等
molecule = qchem.get_molecular_data(
geometry=geo,
basis='sto-3g',
charge=0,
multiplicity=1,
method="fci",
if_save=True,
if_print=True
)
# 提取哈密顿量
molecular_hamiltonian = qchem.spin_hamiltonian(molecule=molecule,
filename=None,
multiplicity=1,
mapping_method='jordan_wigner',)
# 打印结果
print("\nThe generated h2 Hamiltonian is \n", molecular_hamiltonian)
设计量子神经网络QNN(也可以理解为参数化量子电路)来准备试探波函数 |Ψ(θ)⟩。
根据上图中的电路设计,通过 Paddle Quantum 的 Circuit 类和内置的 real_entangled_layer() 电路模板来高效搭建量子神经网络。
def U_theta(num_qubits: int, depth: int) -> Circuit:
"""
Quantum Neural Network
"""
# 按照量子比特数量/网络宽度初始化量子神经网络
cir = Circuit(num_qubits)
# 内置的 {R_y + CNOT} 电路模板
cir.real_entangled_layer(depth = depth)
# 铺上最后一列 R_y 旋转门
cir.ry()
return cir
进一步定义训练参数、模型和损失函数。
class StateNet(paddle.nn.Layer):
"""
Construct the model net
"""
def __init__(self, num_qubits: int, depth: int):
super(StateNet, self).__init__()
self.depth = depth
self.num_qubits = num_qubits
self.cir = U_theta(self.num_qubits, self.depth)
# 定义损失函数和前向传播机制
def forward(self):
# 运行电路
state = self.cir(init_state)
# 计算损失函数
loss = loss_func(state)
return loss, self.cir
进行一些训练的参数设置,主要是学习速率(LR, learning rate)、迭代次数(ITR, iteration)和量子神经网络计算模块的深度(D, Depth)。
ITR = 80 # 设置训练的总迭代次数
LR = 0.4 # 设置学习速率
D = 2 # 设置量子神经网络中重复计算模块的深度 Depth
N = molecular_hamiltonian.n_qubits # 设置参与计算的量子比特数
将数据转化为 Paddle 中的张量,进而进行量子神经网络的训练。
# 确定网络的参数维度
net = StateNet(N, D)
# 一般来说,利用Adam优化器来获得相对好的收敛,
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
# 定义初始态
init_state = zero_state(N)
# 定义损失函数
loss_func = ExpecVal(molecular_hamiltonian)
# 记录优化结果
summary_iter, summary_loss = [], []
# 优化循环
for itr in range(1, ITR + 1):
# 前向传播计算损失函数
loss, cir = net()
# 在动态图机制下,反向传播极小化损失函数
loss.backward()
opt.minimize(loss)
opt.clear_grad()
# 更新优化结果
summary_loss.append(loss.numpy())
summary_iter.append(itr)
# 打印结果
if itr % 20 == 0:
print("iter:", itr, "loss:", "%.4f" % loss.numpy())
print("iter:", itr, "Ground state energy:", "%.4f Ha"
% loss.numpy())
if itr == ITR:
print("\n训练后的电路:")
print(cir)
# 储存训练结果到 output 文件夹
os.makedirs("output", exist_ok=True)
savez("./output/summary_data", iter = summary_iter,
energy=summary_loss)
通过 VQE 得到的基态能量的估计值
result = numpy.load('./output/summary_data.npz')
eig_val, eig_state = numpy.linalg.eig(
molecular_hamiltonian.construct_h_matrix())
min_eig_H = numpy.min(eig_val.real)
min_loss = numpy.ones([len(result['iter'])]) * min_eig_H
plt.figure(1)
func1, = plt.plot(result['iter'], result['energy'],
alpha=0.7, marker='', linestyle="-", color='r')
func_min, = plt.plot(result['iter'], min_loss,
alpha=0.7, marker='', linestyle=":", color='b')
plt.xlabel('Number of iteration')
plt.ylabel('Energy (Ha)')
plt.legend(handles=[
func1,
func_min
],
labels=[
r'$\left\langle {\psi \left( {\theta } \right)} '
r'\right|H\left| {\psi \left( {\theta } \right)} \right\rangle $',
'Ground-state energy',
], loc='best')
plt.text(-15.5, -1.145, f'{min_eig_H:.5f}', fontsize=10, color='b')
#plt.savefig("vqe.png", bbox_inches='tight', dpi=300)
plt.show()
1.5 Tensorflow Quantum(TFQ)框架
TensorFlow Quantum (TFQ) 是一个用于混合量子经典机器学习的 Python 框架,主要为解决NISQ时代的量子机器学习问题而设计。它将量子计算基元(如构建量子电路)引入 TensorFlow 生态系统。使用 TensorFlow 构建的模型和运算使用这些基元来创建功能强大的量子经典混合系统。其允许量子算法研究员和 ML 应用研究员在 TensorFlow 内充分利用 Google 的量子计算框架。
TensorFlow Quantum 实现了将 TensorFlow 与量子计算硬件集成所需的组件。为此,TensorFlow Quantum 引入了两个数据类型基元:
(1)量子电路 - 表示 TensorFlow 中 Cirq 定义的量子电路。创建大小不同的电路批次,类似于不同的实值数据点的批次。
(2)Pauli 和 - 表示 Cirq 中定义的 Pauli 算子张量积的线性组合。像电路一样,创建大小不同的算子批次。
利用这些基元来表示量子电路,TensorFlow Quantum 提供以下运算:
(1)从电路批次的输出分布中采样。
(2)基于电路批次计算 Pauli 和批次的期望值。TFQ 实现了与反向传播兼容的梯度计算。
(3)模拟电路和状态批次。虽然在现实世界中直接检查整个量子电路的所有量子态振幅的效率极低,但状态模拟可以帮助研究员了解量子电路如何将状态映射到接近精确的精度水平。
以上是TensorFlow Quantum 的软件堆栈图,它展示了 TensorFlow 和 Cirq 之间的交互。
TensorFlow Quantum 在 TensorFlow 的基础上增加了处理量子数据的能力。这些量子数据包括量子线路和量子算符。
TensorFlow Quantum 的核心原则是与 TensorFlow,特别是 Keras 模型和优化器的集成,因此,TF Keras Models 横跨了堆栈图的左右。
第三层包含 TensorFlow Quantum 的量子层和微分器,当和经典张量流连接时,可以实现混合量子经典的自动微分。
Ops 层实现了张量流图的实例化。
量子线路可以通过调用 qsim 或 Cirq 模拟运行,或最终在 QPU 上运行。
其操作流程如下:
(1)制备量子数据集:一般而言,量子数据集应当由一个黑盒产生。然而,由于当前的量子计算机无法从外部源导入量子数据,用户需要构造生成数据的量子线路。
(2)量子模型估计:参数化量子模型通过量子计算,来提取量子数据集中隐藏在量子子空间或子系统中的信息。
(3)采样或求平均值:量子态的测量从经典随机变量中以样本的形式提取经典信息。这个随机变量的值的分布通常取决于量子态本身和被测的可观测值。许多变分算法依赖于测量值的平均值,TFQ提供了对前两个步骤的多个运行结果求平均值的方法。
(4)经典模型估计:经典信息被提取出来后,可以进一步做经典后处理,以提取测量期望值之间的关联信息。这一过程可以通过经典深度神经网络实现。
(5)代价函数 (cost function) 估计:得到经典后处理结果后,需要对代价函数进行估计。例如估计监督分类的准确度。
(6)梯度估计和参数更新:完成代价函数的估计之后,整个模型中的自由参数应当向代价降低的方向更新。比较常见的是梯度下降更新。
以下为如何使用 TensorFlow Quantum 构建一个混合的量子经典神经网络。
准备工作:
设置
pip install tensorflow==2.7.0
安装TensorFlow Quantum
pip install tensorflow-quantum
导入 TensorFlow 和模块依赖项
import tensorflow as tf
import tensorflow_quantum as tfq
import cirq
import sympy
import numpy as np
# visualization tools
%matplotlib inline
import matplotlib.pyplot as plt
from cirq.contrib.svg
import SVGCircuit
使用 TensorFlow Quantum 构建一个混合的量子经典神经网络。以下为其架构图:
架构分为 3 个部分:
(1)输入电路或数据点电路:前三个大门。
(2)控制电路:其他三个大门。
(3)控制器:设置受控电路参数的经典神经网络。
操作流程:
步骤1:定义一个可学习的单比特旋转
# Parameters that the classical NN will feed values into.
control_params = sympy.symbols('theta_1 theta_2 theta_3')
# Create the parameterized circuit.
qubit = cirq.GridQubit(0, 0)
model_circuit = cirq.Circuit(
cirq.rz(control_params[0])(qubit),
cirq.ry(control_params[1])(qubit),
cirq.rx(control_params[2])(qubit))
SVGCircuit(model_circuit)
步骤2: 定义控制器网络
# The classical neural network layers.
controller = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation='elu'),
tf.keras.layers.Dense(3)
])
controller(tf.constant([[0.0],[1.0]])).numpy()
步骤3: 将控制器连接到受控电路
# This input is the simulated miscalibration that the model will learn to correct.
circuits_input = tf.keras.Input(shape=(),
# The circuit-tensor has dtype `tf.string`
dtype=tf.string,
name='circuits_input')
# Commands will be either `0` or `1`, specifying the state to set the qubit to.
commands_input = tf.keras.Input(shape=(1,),
dtype=tf.dtypes.float32,
name='commands_input')
步骤4: 对这些输入应用操作,以定义计算
dense_2 = controller(commands_input)
# TFQ layer for classically controlled circuits.
expectation_layer = tfq.layers.ControlledPQC(model_circuit,
# Observe Z
operators = cirq.Z(qubit))
expectation = expectation_layer([circuits_input, dense_2])
步骤5: 将此计算打包为tf.keras.Model
# The full Keras model is built from our layers.
model = tf.keras.Model(inputs=[circuits_input, commands_input],
outputs=expectation)
步骤6: 将模型图与架构图进行比较以验证正确性。
tf.keras.utils.plot_model(model, show_shapes=True, dpi=70)
步骤7:该模型试图输出正确的正确测量值对于每个命令。
# The command input values to the classical NN.
commands = np.array([[0], [1]], dtype=np.float32)
# The desired Z expectation value at output of quantum circuit.
expected_outputs = np.array([[1], [-1]], dtype=np.float32)
步骤8: 输入电路定义模型将学习纠正的随机错误校准
random_rotations = np.random.uniform(0, 2 * np.pi, 3)
noisy_preparation = cirq.Circuit(
cirq.rx(random_rotations[0])(qubit),
cirq.ry(random_rotations[1])(qubit),
cirq.rz(random_rotations[2])(qubit)
)
datapoint_circuits = tfq.convert_to_tensor([
noisy_preparation
] * 2) # Make two copied of this circuit
步骤9:测试运行tfq模型
model([datapoint_circuits, commands]).numpy()
步骤10: 运行一个标准训练过程,将这些值调整为expected_outputs
optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)
loss = tf.keras.losses.MeanSquaredError()
model.compile(optimizer=optimizer, loss=loss) 4. history = model.fit(x=[datapoint_circuits, commands],
y=expected_outputs,
epochs=30,
verbose=0)
plt.plot(history.history['loss'])
plt.title("Learning to Control a Qubit")
plt.xlabel("Iterations")
plt.ylabel("Error in Control")
plt.show()
步骤11: 使用经过训练的模型来纠正量子比特校准错误。
def check_error(command_values, desired_values):
"""Based on the value in `command_value` see how well you could prepare
the full circuit to have `desired_value` when taking expectation w.r.t. Z."""
params_to_prepare_output = controller(command_values).numpy()
full_circuit = noisy_preparation + model_circuit
# Test how well you can prepare a state to get expectation the expectation
# value in `desired_values`
for index in [0, 1]:
state = cirq_simulator.simulate(
full_circuit,
{s:v for (s,v) in zip(control_params, params_to_prepare_output[index])}
).final_state_vector
expt = cirq.Z(qubit).expectation_from_state_vector(state, {qubit: 0}).real
print(f'For a desired output (expectation) of {desired_values[index]} with'
f' noisy preparation, the controller\nnetwork found the following '
f'values for theta: {params_to_prepare_output[index]}\nWhich gives an'
f' actual expectation of: {expt}\n')
check_error(commands, expected_outputs)
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有