特征值分解只适用于方阵,如何扩展到任意形状的矩阵呢?奇异值分解能够解决此问题。量子奇异值阈值算法在奇异值分解的基础上将小的特征值设置为0,从而将小的特征值及其对应的特征向量去掉,进而降低矩阵的秩,达到降维的目的。
奇异值阈值算法
假设A是一个的矩阵,A 的秩记为rank(A)=R。A的奇异值分解是指存在满足和的矩阵和
以及对角矩阵,使得下式成立
(1)
其中为A 的奇异值,u0...和v0...分别为左右奇异量,则A的分解为
(2)
实验
实验中为了简化线路的设计与实现,假设A是方阵,进而可以设置此时奇异值就是特征值,左右奇异值向量就是特征向量。使用的矩阵为
其奇异值和,对应的左右奇异向量分别为
(3)
和
(4)
则算法输入为矩阵A的归一化形式:
(5)
假设阈值,使得矩阵A的两个特征值在执行前后的比例从
变成
第一步:制备初始态
(6)
第二步:利用相位估计将矩阵A 的特征值提取到和上,量子态演化为
(7)
这里,将算子张量上单位矩阵将其扩展到4*4的矩阵,其实只需要将作用到即可。
第三步:通过CNOT门将矩阵A的特征值由和变为和,完成对奇异值的阈值变换,此时量子态演化为
这一步很关键,使得特征值由和,变成了和。
第四步:对进行受控旋转,将新的奇异值相关的信息提取到的概率幅上
第五步:执行第二步和第三步的逆操作,解除和与其他量子的纠缠。
在qasm仿真中添加measure语句会改变最终的测量结果,与理论值有略微的偏差,而不加测量语句,通过自动测量,仿真值与理论值基本吻合。原因还没有找到,但是可以猜测,通过measure语句,当某一条线路已经没有量子逻辑门了,测量便直接进行,而其他的线路仍有量子逻辑门,可能是这样的测量导致了偏差,而统一在所有逻辑门执行完成后测量的值与理论值基本吻合略微好。然而,测量得到的00001,01001,10001,11001的振幅分别为0.0003,0.00009,0.00008,0.00042。特征值比例为3:1,与理论有一定误差。
#量子奇异值阈值分解
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from numpy import pi
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, transpile
from qiskit_aer import Aer
import numpy as np
from qiskit.visualization import plot_histogramfrom math import pi
from qiskit.visualization import plot_histogram
# 创建一个量子电路,包含 4 个量子比特和 4 个经典比特
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from numpy import piqreg_q = QuantumRegister(5, 'q')
creg_c = ClassicalRegister(5, 'c')
circuit = QuantumCircuit(qreg_q, creg_c)circuit.h(qreg_q[3])
circuit.h(qreg_q[2])
circuit.h(qreg_q[1])
circuit.x(qreg_q[3])
circuit.cu(0.635, 0, 0, 0, qreg_q[3], qreg_q[4])
circuit.x(qreg_q[3])
circuit.cu(2.5, 0, 0, 0, qreg_q[3], qreg_q[4])
circuit.cu(-pi / 2, -pi / 2, pi / 2, 0, qreg_q[2], qreg_q[3])
circuit.u(3 * pi / 4, 0, 0, qreg_q[2])
circuit.cx(qreg_q[1], qreg_q[3])
circuit.swap(qreg_q[1], qreg_q[2])
circuit.h(qreg_q[2])
circuit.cu(-pi / 2, 0, 0, 0, qreg_q[1], qreg_q[2])
circuit.h(qreg_q[1])
circuit.cx(qreg_q[1], qreg_q[2])
circuit.cu(-pi / 16, 0, 0, 0, qreg_q[1], qreg_q[0])
circuit.cu(-pi / 32, 0, 0, 0, qreg_q[2], qreg_q[0])
circuit.cx(qreg_q[1], qreg_q[2])
circuit.h(qreg_q[1])
circuit.cu(pi / 2, 0, 0, 0, qreg_q[1], qreg_q[2])
circuit.h(qreg_q[2])
circuit.swap(qreg_q[1], qreg_q[2])
circuit.cx(qreg_q[1], qreg_q[3])
circuit.h(qreg_q[1])
circuit.u(-3 * pi / 4, 0, 0, qreg_q[2])
circuit.cu(-pi / 2, pi / 2, -pi / 2, 0, qreg_q[2], qreg_q[3])
circuit.h(qreg_q[2])
circuit.measure(qreg_q[0], creg_c[0])
circuit.measure(qreg_q[1], creg_c[1])
circuit.measure(qreg_q[2], creg_c[2])
circuit.measure(qreg_q[3], creg_c[3])
circuit.measure(qreg_q[4], creg_c[4])
# Draw the circuit
circuit.draw(output='mpl')