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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions