张量网络量子虚拟机

对于一个 \(N\) 个量子比特的自旋体系,对应的希尔伯特空间维数为 \(2^{N}\)

对于该复杂系统的状态演化,传统的全振幅模拟器将其看做一个有 \(2^{N}\) 个元素的一维向量。

然而从张量网络的角度来看,整个系统量子态的系数对应 \(2^{N}\) 维张量(即N阶张量,即有 \(N\) 个指标,每个指标的维数是2),量子操作算符的系数为 \(2^{2N}\) 维张量( \(2N\) 阶张量,即有个 \(2N\) 指标,每个指标的维数是2),我们可以用如下图形来表示量子态:

../_images/state.png

当量子系统的自旋个数增加时,量子态系数的个数随指数增加,称为指数墙问题,这一障碍限制了传统全振幅模拟器的最大模拟自旋数和模拟性能。

但是可通过张量网络处理这一问题,从而绕过指数墙障碍,在张量网络中,我们对量子系统的模拟,包括量子逻辑门操作和测量操作,均可以通过对于张量的缩并与分解来实现。矩阵乘积态是张量网络中最常用的表示形式,在多线性代数中称为张量列或TT(Tensor-Train),示意图如下。

../_images/MPS.png

将量子态分解成等式右边的表示形式,对于量子线路中部分量子逻辑门操作,可以将全局问题转化为局部的张量处理问题,从而有效地降低了时间复杂度和空间复杂度。

使用介绍

pyqpanda 中可以通过 MPSQVM 类实现用张量网络模拟量子电路。

class MPSQVM(QuantumMachine)

该类实现了基于矩阵乘积态(MPS)的量子线路模拟。可以获取测量结果、模拟量子态等操作。

__init__()

初始化 MPSQVM 类实例。

pmeasure(qubit_list: QVec, select_max: int = -1) List[Tuple[int, float]]

获取量子测量概率分布的列表形式。

参数:
  • qubit_list (QVec) -- 用于测量的量子比特列表。

  • select_max (int, optional) -- 返回的元素数量上限。默认为 -1,表示无限制。

返回:

包含量子测量结果的列表,每个元组包含测量结果的索引和对应的概率。

返回类型:

List[Tuple[int, float]]

pmeasure_bin_index(program: QProg, string: str) complex

获取指定二进制字符串的量子态振幅。

参数:
  • program (QProg) -- 要运行的量子程序。

  • string (str) -- 二进制字符串。

返回:

指定二进制字符串的量子态振幅。

返回类型:

complex

抛出:

run_fail -- 获取振幅失败。

pmeasure_bin_subset(program: QProg, string_list: List[str]) List[complex]

获取一组二进制字符串的量子态振幅。

参数:
  • program (QProg) -- 要运行的量子程序。

  • string_list (List[str]) -- 二进制字符串列表。

返回:

一组二进制字符串的量子态振幅。

返回类型:

List[complex]

抛出:

run_fail -- 获取振幅失败。

pmeasure_dec_index(program: QProg, string: str) complex

获取指定十进制字符串的量子态振幅。

参数:
  • program (QProg) -- 要运行的量子程序。

  • string (str) -- 十进制字符串。

返回:

指定十进制字符串的量子态振幅。

返回类型:

complex

抛出:

run_fail -- 获取振幅失败。

pmeasure_dec_subset(program: QProg, string_list: List[str]) List[complex]

获取一组十进制字符串的量子态振幅。

参数:
  • program (QProg) -- 要运行的量子程序。

  • string_list (List[str]) -- 十进制字符串列表。

返回:

一组十进制字符串的量子态振幅。

返回类型:

List[complex]

抛出:

run_fail -- 获取振幅失败。

prob_run_dict(program: QProg, qubit_list: QVec, select_max: int = -1) Dict[str, float]

运行量子程序并获取测量概率结果的字典形式。

参数:
  • program (QProg) -- 要运行的量子程序。

  • qubit_list (QVec) -- 用于测量的量子比特列表。

  • select_max (int, optional) -- 返回的元素数量上限。默认为 -1,表示无限制。

返回:

包含测量概率的字典,键为测量结果的二进制字符串,值为对应的测量概率。

返回类型:

Dict[str, float]

抛出:

run_fail -- 运行量子程序失败。

prob_run_list(program: QProg, qubit_list: QVec, select_max: int = -1) List[float]

运行量子程序并获取测量概率结果的列表形式。

参数:
  • program (QProg) -- 要运行的量子程序。

  • qubit_list (QVec) -- 用于测量的量子比特列表。

  • select_max (int, optional) -- 返回的元素数量上限。默认为 -1,表示无限制。

返回:

包含测量概率的列表。

返回类型:

List[float]

抛出:

run_fail -- 运行量子程序失败。

prob_run_tuple_list(program: QProg, qubit_list: QVec, select_max: int = -1) List[Tuple[int, float]]

运行量子程序并获取测量概率结果的元组列表形式。

参数:
  • program (QProg) -- 要运行的量子程序。

  • qubit_list (QVec) -- 用于测量的量子比特列表。

  • select_max (int, optional) -- 返回的元素数量上限。默认为 -1,表示无限制。

返回:

包含测量概率的元组列表,每个元组包含测量结果的索引和对应的概率。

返回类型:

List[Tuple[int, float]]

抛出:

run_fail -- 运行量子程序失败。

quick_measure(qubit_list: QVec, shots: int) Dict[str, int]

快速进行多次测量。

参数:
  • qubit_list (QVec) -- 用于测量的量子比特列表。

  • shots (int) -- 测量操作的重复次数。

返回:

包含多次测量结果的字典,键为测量结果的二进制字符串,值为对应的出现次数。

返回类型:

Dict[str, int]

抛出:

run_fail -- 运行量子程序失败。

set_measure_error(noise_model: NoiseModel, error_rate: float, gate_type: GateType = GateType.HADAMARD_GATE, qubits: List[QVec] = []) None

设置测量误差模型。

参数:
  • noise_model (NoiseModel) -- 噪声模型。

  • error_rate (float) -- 误差率。

  • gate_type (GateType, optional) -- 误差应用的门类型。默认为 GateType.HADAMARD_GATE。

  • qubits (List[QVec], optional) -- 用于应用误差的量子比特列表。默认为空列表。

返回:

无返回值。

set_mixed_unitary_error(gate_type: GateType, error_matrix: List[List[complex]], qubits: List[QVec] = []) None

设置混合幺正误差模型。

参数:
  • gate_type (GateType) -- 门类型。

  • error_matrix (List[List[complex]]) -- 误差矩阵。

  • qubits (List[QVec], optional) -- 用于应用误差的量子比特列表。默认为空列表。

返回:

无返回值。

set_noise_model(noise_model: NoiseModel, gate_type: GateType, error_rate: float, qubits: List[QVec] = []) None

设置噪声模型。

参数:
  • noise_model (NoiseModel) -- 噪声模型。

  • gate_type (GateType) -- 误差应用的门类型。

  • error_rate (float) -- 误差率。

  • qubits (List[QVec], optional) -- 用于应用误差的量子比特列表。默认为空列表。

返回:

无返回值。

set_readout_error(readout_params: List[List[float]], qubits: QVec) None

设置读数误差模型。

参数:
  • readout_params (List[List[float]]) -- 读数误差参数列表。

  • qubits (QVec) -- 用于应用误差的量子比特列表。

返回:

无返回值。

set_reset_error(reset_0_param: float, reset_1_param: float) None

设置重置误差模型。

参数:
  • reset_0_param (float) -- 重置到0态的参数。

  • reset_1_param (float) -- 重置到1态的参数。

返回:

无返回值。

set_rotation_error(param: float) None

设置旋转门误差模型。

参数:

param (float) -- 误差参数。

返回:

无返回值。

和许多其他模拟器的使用方法一样,都具有相同的量子虚拟机接口,比如下述简单的使用示例代码:

from numpy import pi
from pyqpanda import *

# 构建量子虚拟机
qvm = MPSQVM()

# 初始化操作
qvm.set_configure(64, 64)
qvm.init_qvm()

q = qvm.qAlloc_many(10)
c = qvm.cAlloc_many(10)

# 构建量子程序
prog = QProg()
prog << hadamard_circuit(q)\
    << CZ(q[2], q[4])\
    << CZ(q[3], q[7])\
    << CNOT(q[0], q[1])\
    << Measure(q[0], c[0])\
    << Measure(q[1], c[1])\
    << Measure(q[2], c[2])\
    << Measure(q[3], c[3])

# 量子程序运行100次,并返回测量结果
result = qvm.run_with_configuration(prog, c, 100)

# 打印量子态在量子程序多次运行结果中出现的次数
print(result)

qvm.finalize()

完整示例代码


以下示例展示了张量网络模拟器计算部分接口的使用方式

from numpy import pi
from pyqpanda import *

qvm = MPSQVM()
qvm.set_configure(64, 64)
qvm.init_qvm()

q = qvm.qAlloc_many(10)
c = qvm.cAlloc_many(10)

prog = QProg()
prog << hadamard_circuit(q)\
    << CZ(q[2], q[4])\
    << CZ(q[3], q[7])\
    << CNOT(q[0], q[1])\
    << CZ(q[3], q[7])\
    << CZ(q[0], q[4])\
    << RY(q[7], pi / 2)\
    << RX(q[8], pi / 2)\
    << RX(q[9], pi / 2)\
    << CR(q[0], q[1], pi)\
    << CR(q[2], q[3], pi)\
    << RY(q[4], pi / 2)\
    << RZ(q[5], pi / 4)\
    << Measure(q[0], c[0])\
    << Measure(q[1], c[1])\
    << Measure(q[2], c[2])

# Monte Carlo采样模拟接口
result0 = qvm.run_with_configuration(prog, c, 100)

# 概率测量接口
result1 = qvm.prob_run_dict(prog, [q[0], q[1], q[2]], -1)

print(result0)
print(result1)

qvm.finalize()

上述代码中 run_with_configurationprob_run_dict 接口分别用于Monte Carlo采样模拟和概率测量,他们分别输出模拟采样的结果和对应振幅的概率,上述程序的计算结果如下

# Monte Carlo 采样模拟结果
{'0000000000': 7,
 '0000000001': 12,
 '0000000010': 13,
 '0000000011': 10,
 '0000000100': 16,
 '0000000101': 14,
 '0000000110': 12,
 '0000000111': 16}

# 概率测量结果
{'000': 0.12499999999999194,
 '001': 0.12499999999999185,
 '010': 0.12499999999999194,
 '011': 0.124999999999992,
 '100': 0.12499999999999198,
 '101': 0.12499999999999194,
 '110': 0.12499999999999198,
 '111': 0.12499999999999208}