Skip to content

Unexpected simulated unitary for QFT and IQFT #252

@gtaifu

Description

@gtaifu

QPanda

基本信息

  • QPanda 版本: pyqpanda 3.8.5
  • 操作系统:Windows 11

Bug是什么?

使用QPanda产生的QFT和IQFT的矩阵与预期不一致

复现Bug的步骤?

使用如下代码:

"""
使用 PyQPanda 打印 3 量子比特 QFT 和 IQFT 的酉矩阵

本脚本演示如何使用 PyQPanda 库构建量子傅里叶变换(QFT)和
逆量子傅里叶变换(IQFT)电路,并获取对应的酉矩阵。
"""

import numpy as np
import pyqpanda as pq


def print_complex_matrix(mat, epsilon=1e-8, precision=4):
    """
    精简打印 NumPy 复数矩阵,忽略实/虚部小于 epsilon 的部分。
    同一列元素对齐显示,便于观看方阵结构。

    参数:
    - mat: NumPy 数组(矩阵)
    - epsilon: 阈值,默认为 1e-8
    - precision: 格式化精度,默认为 4 位有效数字
    """
    def format_complex(val):
        """格式化单个复数,力求精简"""
        real = val.real
        imag = val.imag
        if abs(real) < epsilon and abs(imag) < epsilon:
            return '0'
        elif abs(real) < epsilon:
            return f'{imag:.{precision}g}j'
        elif abs(imag) < epsilon:
            return f'{real:.{precision}g}'
        else:
            sign = '+' if imag >= 0 else '-'
            return f'{real:.{precision}g}{sign}{abs(imag):.{precision}g}j'

    # 先生成所有格式化的字符串
    n_rows = len(mat)
    n_cols = len(mat[0]) if n_rows > 0 else 0

    formatted = [[format_complex(mat[i][j]) for j in range(n_cols)] for i in range(n_rows)]

    # 计算每列的最大宽度
    col_widths = [max(len(formatted[i][j]) for i in range(n_rows)) for j in range(n_cols)]

    # 打印对齐的矩阵
    rows = []
    for i in range(n_rows):
        row_str = [formatted[i][j].rjust(col_widths[j]) for j in range(n_cols)]
        rows.append('[' + '  '.join(row_str) + ']')
    print('[' + '\n '.join(rows) + ']')

from qututor.qft.utils import (
    get_output_filepath,
    print_complex_matrix,
    tee_output,
    verify_qft_iqft,
)


def get_qft_matrix_pyqpanda(num_qubits):
    """
    使用 PyQPanda 获取 QFT 的酉矩阵

    Args:
        num_qubits: 量子比特数量

    Returns:
        QFT 对应的酉矩阵 (numpy array)
    """
    # 初始化量子虚拟机
    machine = pq.CPUQVM()
    machine.init_qvm()

    # 分配量子比特
    qvec = machine.qAlloc_many(num_qubits)

    # 构建 QFT 量子程序
    prog = pq.QProg()
    prog << pq.QFT(qvec)

    # 获取酉矩阵
    matrix = pq.get_matrix(prog)

    # 释放资源
    machine.finalize()

    # 将一维数组重塑为二维矩阵
    dim = 2 ** num_qubits
    return np.array(matrix).reshape(dim, dim)


def get_iqft_matrix_pyqpanda(num_qubits):
    """
    使用 PyQPanda 获取 IQFT 的酉矩阵

    Args:
        num_qubits: 量子比特数量

    Returns:
        IQFT 对应的酉矩阵 (numpy array)
    """
    # 初始化量子虚拟机
    machine = pq.CPUQVM()
    machine.init_qvm()

    # 分配量子比特
    qvec = machine.qAlloc_many(num_qubits)

    # 构建 IQFT 量子程序 (QFT 的逆)
    prog = pq.QProg()
    # QFT 的第二个参数为 True 表示执行逆变换
    prog << pq.QFT(qvec).dagger()

    # 获取酉矩阵
    matrix = pq.get_matrix(prog)

    # 释放资源
    machine.finalize()

    # 将一维数组重塑为二维矩阵
    dim = 2 ** num_qubits
    return np.array(matrix).reshape(dim, dim)


def main():
    num_qubits = 3

    # 输出文件路径(与脚本同目录)
    output_file = "pyqpanda_qft_matrix_output.txt"

    with tee_output(output_file):
        print(f"=" * 60)
        print(f"PyQPanda: {num_qubits} 量子比特 QFT 和 IQFT 酉矩阵")
        print(f"=" * 60)

        # 获取 QFT 酉矩阵
        print(f"\n{'='*20} QFT 酉矩阵 {'='*20}")
        qft_matrix = get_qft_matrix_pyqpanda(num_qubits)
        print(f"矩阵维度: {qft_matrix.shape}")
        print()
        print_complex_matrix(qft_matrix)

        # 获取 IQFT 酉矩阵
        print(f"\n{'='*20} IQFT 酉矩阵 {'='*20}")
        iqft_matrix = get_iqft_matrix_pyqpanda(num_qubits)
        print(f"矩阵维度: {iqft_matrix.shape}")
        print()
        print_complex_matrix(iqft_matrix)

        # 验证 QFT * IQFT = I
        print(f"\n{'='*20} 验证 {'='*20}")
        is_valid = verify_qft_iqft(qft_matrix, iqft_matrix)
        print(f"QFT × IQFT = I: {'✓ 通过' if is_valid else '✗ 失败'}")

        # 额外:打印 QFT * IQFT 的结果
        print(f"\n{'='*20} QFT × IQFT 结果 {'='*20}")
        product = np.dot(qft_matrix, iqft_matrix)
        print_complex_matrix(product)

    print(f"\n结果已保存到: {output_file}")


if __name__ == "__main__":
    main()

上述代码打印的QFT和IQFT的矩阵分别为:


==================== QFT 酉矩阵 ====================
矩阵维度: (8, 8)

[[0.3536   0.3536    0.3536    0.3536       0.3536       0.3536       0.3536       0.3536]
 [0.3536   0.3536    0.3536    0.3536      -0.3536      -0.3536      -0.3536      -0.3536]
 [0.3536   0.3536   -0.3536   -0.3536      0.3536j      0.3536j     -0.3536j     -0.3536j]
 [0.3536   0.3536   -0.3536   -0.3536     -0.3536j     -0.3536j      0.3536j      0.3536j]
 [0.3536  -0.3536   0.3536j  -0.3536j   0.25+0.25j  -0.25-0.25j  -0.25+0.25j   0.25-0.25j]
 [0.3536  -0.3536   0.3536j  -0.3536j  -0.25-0.25j   0.25+0.25j   0.25-0.25j  -0.25+0.25j]
 [0.3536  -0.3536  -0.3536j   0.3536j  -0.25+0.25j   0.25-0.25j   0.25+0.25j  -0.25-0.25j]
 [0.3536  -0.3536  -0.3536j   0.3536j   0.25-0.25j  -0.25+0.25j  -0.25-0.25j   0.25+0.25j]]

==================== IQFT 酉矩阵 ====================
矩阵维度: (8, 8)

[[0.3536   0.3536    0.3536    0.3536       0.3536       0.3536       0.3536       0.3536]
 [0.3536   0.3536    0.3536    0.3536      -0.3536      -0.3536      -0.3536      -0.3536]
 [0.3536   0.3536   -0.3536   -0.3536     -0.3536j     -0.3536j      0.3536j      0.3536j]
 [0.3536   0.3536   -0.3536   -0.3536      0.3536j      0.3536j     -0.3536j     -0.3536j]
 [0.3536  -0.3536  -0.3536j   0.3536j   0.25-0.25j  -0.25+0.25j  -0.25-0.25j   0.25+0.25j]
 [0.3536  -0.3536  -0.3536j   0.3536j  -0.25+0.25j   0.25-0.25j   0.25+0.25j  -0.25-0.25j]
 [0.3536  -0.3536   0.3536j  -0.3536j  -0.25-0.25j   0.25+0.25j   0.25-0.25j  -0.25+0.25j]
 [0.3536  -0.3536   0.3536j  -0.3536j   0.25+0.25j  -0.25-0.25j  -0.25+0.25j   0.25-0.25j]]

但使用dft得到的结果如下:

============================================================
NumPy: 3 量子比特 (8 维) DFT 和 IDFT 矩阵
============================================================

==================== DFT 公式 ====================
F[j,k] = exp(2πi * j * k / N) / sqrt(N)
其中 N = 2^3 = 8, j,k ∈ [0, 7]

==================== DFT 矩阵 ====================
矩阵维度: (8, 8)

[[0.3536       0.3536    0.3536       0.3536   0.3536       0.3536    0.3536       0.3536]
 [0.3536   0.25+0.25j   0.3536j  -0.25+0.25j  -0.3536  -0.25-0.25j  -0.3536j   0.25-0.25j]
 [0.3536      0.3536j   -0.3536     -0.3536j   0.3536      0.3536j   -0.3536     -0.3536j]
 [0.3536  -0.25+0.25j  -0.3536j   0.25+0.25j  -0.3536   0.25-0.25j   0.3536j  -0.25-0.25j]
 [0.3536      -0.3536    0.3536      -0.3536   0.3536      -0.3536    0.3536      -0.3536]
 [0.3536  -0.25-0.25j   0.3536j   0.25-0.25j  -0.3536   0.25+0.25j  -0.3536j  -0.25+0.25j]
 [0.3536     -0.3536j   -0.3536      0.3536j   0.3536     -0.3536j   -0.3536      0.3536j]
 [0.3536   0.25-0.25j  -0.3536j  -0.25-0.25j  -0.3536  -0.25+0.25j   0.3536j   0.25+0.25j]]

==================== IDFT 公式 ====================
F^(-1)[j,k] = exp(-2πi * j * k / N) / sqrt(N)
对于酉矩阵: IDFT = DFT^H (共轭转置)

==================== IDFT 矩阵 ====================
矩阵维度: (8, 8)

[[0.3536       0.3536    0.3536       0.3536   0.3536       0.3536    0.3536       0.3536]
 [0.3536   0.25-0.25j  -0.3536j  -0.25-0.25j  -0.3536  -0.25+0.25j   0.3536j   0.25+0.25j]
 [0.3536     -0.3536j   -0.3536      0.3536j   0.3536     -0.3536j   -0.3536      0.3536j]
 [0.3536  -0.25-0.25j   0.3536j   0.25-0.25j  -0.3536   0.25+0.25j  -0.3536j  -0.25+0.25j]
 [0.3536      -0.3536    0.3536      -0.3536   0.3536      -0.3536    0.3536      -0.3536]
 [0.3536  -0.25+0.25j  -0.3536j   0.25+0.25j  -0.3536   0.25-0.25j   0.3536j  -0.25-0.25j]
 [0.3536      0.3536j   -0.3536     -0.3536j   0.3536      0.3536j   -0.3536     -0.3536j]
 [0.3536   0.25+0.25j   0.3536j  -0.25+0.25j  -0.3536  -0.25-0.25j  -0.3536j   0.25-0.25j]]

我做了如下尝试:

  • 我无法通过行列变换使得DFT的结果与qpanda的结果一致。
  • 我无法利用qpanda来控制是否添加 swap门
  • 这个差异并非一个全局相位差(因为两边的矩阵的第一个数是相等的实数)

建议的解决方案

无。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions