生成旋转表面码图示的完整 Python 源代码

以下是生成旋转表面码图示的完整 Python 源代码,已保存为可直接运行的脚本:

rotated_surface_code.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
旋转表面码(Rotated Surface Code)可视化生成器
=================================================
生成旋转表面码的布局图、逻辑算符图以及错误链纠错演示图。

依赖:matplotlib, numpy
运行:python rotated_surface_code.py
"""

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np


def draw_rotated_surface_code(d, ax=None, show_logical=False, title=None):
    """
    绘制旋转表面码的完整布局。

    参数
    ----------
    d : int
        码距(distance),数据量子比特排列为 d x d 方阵。
    ax : matplotlib.axes.Axes, optional
        目标绘图轴。若为 None,则创建新图。
    show_logical : bool
        是否绘制逻辑算符 X̄ 和 Z̄。
    title : str, optional
        图标题。

    返回
    -------
    ax : matplotlib.axes.Axes
        绘图轴对象。
    """
    if ax is None:
        fig, ax = plt.subplots(figsize=(10, 10))

    # ---------- 数据量子比特(蓝色圆点) ----------
    for i in range(d):
        for j in range(d):
            ax.plot(i, j, 'o', markersize=26, color='steelblue', zorder=3)
            ax.text(i, j, 'D', ha='center', va='center', fontsize=10,
                    color='white', fontweight='bold', zorder=4)

    # ---------- 内部稳定子(plaquettes) ----------
    # 棋盘格交替排列:X型(红色)和 Z型(绿色)
    for i in range(d - 1):
        for j in range(d - 1):
            x = i + 0.5
            y = j + 0.5
            if (i + j) % 2 == 0:
                # X型稳定子(红色)
                rect = patches.Rectangle(
                    (x - 0.35, y - 0.35), 0.7, 0.7,
                    linewidth=2.5, edgecolor='crimson',
                    facecolor='lightcoral', alpha=0.35, zorder=2
                )
                ax.add_patch(rect)
                ax.text(x, y, 'X', ha='center', va='center', fontsize=16,
                        color='darkred', fontweight='bold', zorder=5)
                # 连线到4个相邻数据量子比特
                for di, dj in [(0, 0), (1, 0), (0, 1), (1, 1)]:
                    ax.plot([x, i + di], [y, j + dj], 'r-',
                            alpha=0.25, linewidth=1.5, zorder=1)
            else:
                # Z型稳定子(绿色)
                rect = patches.Rectangle(
                    (x - 0.35, y - 0.35), 0.7, 0.7,
                    linewidth=2.5, edgecolor='forestgreen',
                    facecolor='lightgreen', alpha=0.35, zorder=2
                )
                ax.add_patch(rect)
                ax.text(x, y, 'Z', ha='center', va='center', fontsize=16,
                        color='darkgreen', fontweight='bold', zorder=5)
                for di, dj in [(0, 0), (1, 0), (0, 1), (1, 1)]:
                    ax.plot([x, i + di], [y, j + dj], 'g-',
                            alpha=0.25, linewidth=1.5, zorder=1)

    # ---------- 边界标注 ----------
    # 粗糙边界(Rough Boundary,X型):上下边界
    for i in range(d):
        ax.plot([i - 0.15, i + 0.15], [d - 1 + 0.55, d - 1 + 0.55],
                'r-', linewidth=4, alpha=0.7)
        ax.plot([i - 0.15, i + 0.15], [-0.55, -0.55],
                'r-', linewidth=4, alpha=0.7)

    # 平滑边界(Smooth Boundary,Z型):左右边界
    for j in range(d):
        ax.plot([-0.55, -0.55], [j - 0.15, j + 0.15],
                'g-', linewidth=4, alpha=0.7)
        ax.plot([d - 1 + 0.55, d - 1 + 0.55], [j - 0.15, j + 0.15],
                'g-', linewidth=4, alpha=0.7)

    # 边界文字标注
    ax.text(d / 2 - 0.5, d - 1 + 0.85, 'Rough Boundary (X-type)',
            ha='center', va='bottom', fontsize=11,
            color='crimson', fontweight='bold')
    ax.text(d / 2 - 0.5, -0.85, 'Rough Boundary (X-type)',
            ha='center', va='top', fontsize=11,
            color='crimson', fontweight='bold')
    ax.text(-0.85, d / 2 - 0.5, 'Smooth Boundary (Z-type)',
            ha='center', va='center', fontsize=11,
            color='forestgreen', fontweight='bold', rotation=90)
    ax.text(d - 1 + 0.85, d / 2 - 0.5, 'Smooth Boundary (Z-type)',
            ha='center', va='center', fontsize=11,
            color='forestgreen', fontweight='bold', rotation=270)

    # ---------- 逻辑算符 ----------
    if show_logical:
        mid = d // 2

        # 逻辑 X̄:垂直路径,连接上下粗糙边界,重量为 d
        x_path = [mid] * d
        y_path = list(range(d))
        ax.plot(x_path, y_path, 'r-', linewidth=6, alpha=0.5, zorder=6,
                label=f'Logical X̄  (weight = {d})')
        for x, y in zip(x_path, y_path):
            ax.scatter(x, y, s=400, c='red', marker='x', linewidth=4, zorder=7)

        # 逻辑 Z̄:水平路径,连接左右平滑边界,重量为 d
        x_path = list(range(d))
        y_path = [mid] * d
        ax.plot(x_path, y_path, 'g-', linewidth=6, alpha=0.5, zorder=6,
                label=f'Logical Z̄  (weight = {d})')
        for x, y in zip(x_path, y_path):
            ax.scatter(x, y, s=400, c='green', marker='o',
                       facecolors='none', edgecolors='green', linewidth=4, zorder=7)

        ax.legend(loc='upper right', fontsize=12, framealpha=0.95,
                  edgecolor='black', fancybox=True)

    # ---------- 坐标轴设置 ----------
    margin = 1.5
    ax.set_xlim(-margin, d - 1 + margin)
    ax.set_ylim(-margin, d - 1 + margin)
    ax.set_aspect('equal')
    ax.axis('off')

    if title:
        ax.set_title(title, fontsize=14, fontweight='bold', pad=20)

    return ax


def draw_error_demo(d, ax, error_qubits, syndrome_plaquettes, title, description):
    """
    绘制错误链演示图,展示 syndrome 检测与纠错边界。

    参数
    ----------
    d : int
        码距。
    ax : matplotlib.axes.Axes
        目标绘图轴。
    error_qubits : set of tuple
        发生错误的 (i, j) 数据量子比特坐标集合。
    syndrome_plaquettes : set of tuple
        产生非零 syndrome 的 plaquette 坐标 (i, j) 集合。
    title : str
        图标题。
    description : str
        副标题描述。
    """
    # 数据量子比特
    for i in range(d):
        for j in range(d):
            if (i, j) in error_qubits:
                # 错误的数据量子比特(黄色高亮)
                ax.plot(i, j, 'o', markersize=28, color='gold', zorder=3)
                ax.text(i, j, 'E', ha='center', va='center', fontsize=10,
                        color='darkred', fontweight='bold', zorder=4)
            else:
                ax.plot(i, j, 'o', markersize=26, color='steelblue', zorder=3)
                ax.text(i, j, 'D', ha='center', va='center', fontsize=9,
                        color='white', fontweight='bold', zorder=4)

    # 内部稳定子
    for i in range(d - 1):
        for j in range(d - 1):
            x = i + 0.5
            y = j + 0.5
            is_syndrome = (i, j) in syndrome_plaquettes

            if (i + j) % 2 == 0:
                color = 'crimson' if is_syndrome else 'lightcoral'
                edge = 'darkred' if is_syndrome else 'crimson'
                alpha = 0.8 if is_syndrome else 0.25
                label = 'S' if is_syndrome else 'X'
                text_color = 'yellow' if is_syndrome else 'darkred'
            else:
                color = 'forestgreen' if is_syndrome else 'lightgreen'
                edge = 'darkgreen' if is_syndrome else 'forestgreen'
                alpha = 0.8 if is_syndrome else 0.25
                label = 'S' if is_syndrome else 'Z'
                text_color = 'yellow' if is_syndrome else 'darkgreen'

            rect = patches.Rectangle(
                (x - 0.35, y - 0.35), 0.7, 0.7,
                linewidth=3 if is_syndrome else 2,
                edgecolor=edge, facecolor=color, alpha=alpha, zorder=2
            )
            ax.add_patch(rect)
            ax.text(x, y, label, ha='center', va='center',
                    fontsize=16 if is_syndrome else 14,
                    color=text_color, fontweight='bold', zorder=5)

            for di, dj in [(0, 0), (1, 0), (0, 1), (1, 1)]:
                line_color = 'orange' if is_syndrome else ('red' if (i + j) % 2 == 0 else 'green')
                lw = 2.5 if is_syndrome else 1.5
                ax.plot([x, i + di], [y, j + dj], color=line_color,
                        alpha=0.6 if is_syndrome else 0.2, linewidth=lw, zorder=1)

    # 边界
    for i in range(d):
        ax.plot([i - 0.15, i + 0.15], [d - 1 + 0.55, d - 1 + 0.55],
                'r-', linewidth=3, alpha=0.5)
        ax.plot([i - 0.15, i + 0.15], [-0.55, -0.55],
                'r-', linewidth=3, alpha=0.5)
    for j in range(d):
        ax.plot([-0.55, -0.55], [j - 0.15, j + 0.15],
                'g-', linewidth=3, alpha=0.5)
        ax.plot([d - 1 + 0.55, d - 1 + 0.55], [j - 0.15, j + 0.15],
                'g-', linewidth=3, alpha=0.5)

    # 错误链连线(虚线)
    if len(error_qubits) > 1:
        eq_list = sorted(list(error_qubits))
        for k in range(len(eq_list) - 1):
            x1, y1 = eq_list[k]
            x2, y2 = eq_list[k + 1]
            ax.plot([x1, x2], [y1, y2], 'y--', linewidth=4, alpha=0.8, zorder=6)

    ax.set_xlim(-1.2, d)
    ax.set_ylim(-1.2, d)
    ax.set_aspect('equal')
    ax.axis('off')
    ax.set_title(f'{title}\n{description}', fontsize=12, fontweight='bold', pad=15)


def main():
    """主函数:生成三幅旋转表面码图示并保存。"""

    # ==================== 图1:d=3 布局与逻辑算符 ====================
    fig, axes = plt.subplots(1, 2, figsize=(18, 9))
    draw_rotated_surface_code(
        3, ax=axes[0], show_logical=False,
        title='Rotated Surface Code (d = 3)\nLayout & Stabilizers'
    )
    draw_rotated_surface_code(
        3, ax=axes[1], show_logical=True,
        title='Rotated Surface Code (d = 3)\nLogical Operators & Minimum Distance'
    )
    plt.tight_layout()
    plt.savefig('rotated_surface_code_d3.png', dpi=200, bbox_inches='tight',
                facecolor='white', edgecolor='none')
    plt.show()
    print("[保存] rotated_surface_code_d3.png")

    # ==================== 图2:d=5 逻辑算符 ====================
    fig, ax = plt.subplots(figsize=(12, 12))
    draw_rotated_surface_code(
        5, ax=ax, show_logical=True,
        title='Rotated Surface Code (d = 5)\nLogical Operators & Minimum Distance'
    )
    plt.tight_layout()
    plt.savefig('rotated_surface_code_d5.png', dpi=200, bbox_inches='tight',
                facecolor='white', edgecolor='none')
    plt.show()
    print("[保存] rotated_surface_code_d5.png")

    # ==================== 图3:错误链演示 ====================
    fig, axes = plt.subplots(1, 3, figsize=(21, 7))

    # 场景1:单个错误(可纠正)
    draw_error_demo(
        3, axes[0],
        error_qubits={(1, 1)},
        syndrome_plaquettes={(0, 0), (0, 1), (1, 0), (1, 1)},
        title='Scenario 1: Single Error (Correctable)',
        description='Weight-1 error → 4 syndromes detected\nCan be corrected'
    )

    # 场景2:两个错误形成短链(可纠正,因为长度 < d)
    draw_error_demo(
        3, axes[1],
        error_qubits={(1, 0), (1, 1)},
        syndrome_plaquettes={(0, 0), (0, 1)},
        title='Scenario 2: Two Errors (Correctable)',
        description='Weight-2 chain → 2 syndromes at endpoints\nChain length < d'
    )

    # 场景3:跨越边界的错误链(不可纠正,形成逻辑错误)
    draw_error_demo(
        3, axes[2],
        error_qubits={(1, 0), (1, 1), (1, 2)},
        syndrome_plaquettes=set(),  # 边界上无syndrome(与边界稳定子对易)
        title='Scenario 3: Logical Error (Uncorrectable)',
        description='Weight-3 chain spans full distance d=3\nEquivalent to Logical X̄'
    )

    plt.tight_layout()
    plt.savefig('rotated_surface_code_error_chains.png', dpi=200, bbox_inches='tight',
                facecolor='white', edgecolor='none')
    plt.show()
    print("[保存] rotated_surface_code_error_chains.png")

    print("\n所有图示已生成完毕!")


if __name__ == '__main__':
    main()

使用说明:

  1. 安装依赖pip install matplotlib numpy
  2. 运行脚本python rotated_surface_code.py
  3. 输出文件:脚本会生成三幅 PNG 图片并弹出显示窗口

代码结构:

函数功能
draw_rotated_surface_code(d, ...)绘制 d×dd \times dd×d 旋转表面码的完整布局,可选叠加逻辑算符 Xˉ\bar{X}Xˉ(红色竖链)和 Zˉ\bar{Z}Zˉ(绿色横链)
draw_error_demo(d, ...)绘制错误链演示,高亮错误量子比特(黄色 E)、syndrome 激活的 plaquette(深绿色/深红色 S),以及错误链路径
main()依次生成 d=3 布局图、d=5 逻辑算符图、三场景错误链演示图

可以直接修改 main() 中的参数(如将 d=5 改为 d=7)来生成更大码距的图示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值