Skip to content

QCloud Fidelity Layout 完整工作流 ​

本教程展示 pyqpanda3 0.4.0 的完整硬件感知路径:

  1. 获取 QCloud 实时芯片元数据。
  2. 将芯片元数据转换为 ChipBackend。
  3. 使用同一个 ChipBackend 完成保真度感知布局和转译。
  4. 根据芯片元数据中的时序导出带时间戳的指令流。
  5. 在本地预览时序图。
  6. 使用 run_instruction() 提交同一份指令流。

不要在源码或文档中硬编码 API key。下面示例统一从环境变量 QPANDA_QCLOUD_API_KEY 读取。

为什么必须从 chip_info() 开始 ​

run_instruction() 接收 instruction JSON,所以手写一段短指令看起来很方便。手写指令适合排查格式问题,但不是推荐的真实硬件流程。

面向 QCloud 后端时,应从 chip_info() 构建指令流:

核心原则很简单:用于布局的后端对象,也应该继续用于指令导出和时序绘图。

一步完成保真度布局、调度和提交 ​

这条路径通过 layout_method="fidelity" 让 Transpiler 在内部调用 fidelity layout。

python
import os

from pyqpanda3.core import CZ, H, QProg, measure
from pyqpanda3.qcloud import QCloudOptions, QCloudService
from pyqpanda3.transpilation import Transpiler, decompose
from pyqpanda3.visualization import draw_time_scheduling


def build_program():
    prog = QProg()
    prog << H(0)
    prog << H(1)
    prog << CZ(0, 1)
    prog << CZ(1, 2)
    prog << measure(0, 0)
    prog << measure(1, 1)
    prog << measure(2, 2)
    return prog


service = QCloudService(os.environ["QPANDA_QCLOUD_API_KEY"])
qcloud_backend = service.backend(os.environ.get("QPANDA_QCLOUD_BACKEND", "WK_C180"))

chip_info = qcloud_backend.chip_info()
chip_backend = chip_info.get_chip_backend()
print("backend:", qcloud_backend.name())
print("timing:", chip_backend.single_gate_timing, chip_backend.double_gate_timing)

prog = build_program()
decomposed = decompose(prog, ["U3", "CZ"])
transpiled = Transpiler().transpile(decomposed, chip_backend, {}, 2, "fidelity")

# is_scheduling=True 会让 to_instruction 使用 chip_backend 中的单双门时序,
# 而不是依赖文档里手写的时间戳。
instruction = transpiled.to_instruction(
    chip_backend,
    offset=1,
    is_scheduling=True,
    compensate_pulse=False,
)

figures = draw_time_scheduling(instruction, backend=chip_backend, output="plotly")
print("schedule figure:", type(figures).__name__)

options = QCloudOptions()
options.set_mapping(False)
options.set_optimization(False)
options.set_amend(False)

job = qcloud_backend.run_instruction([instruction], 1000, options)
result = job.result()

print(result.get_counts_list())

示例输出形态:

text
backend: WK_C180
timing: 40 80
schedule figure: Figure
[{'000': 263, '001': 229, '010': 241, '011': 227, '100': 6, '101': 4, '110': 15, '111': 15}]

时序和计数会随后端与标定快照变化。这里真正重要的是:指令时间戳来自 QCloud 返回的 ChipBackend,不是文档里的固定常量。

提交前检查初始布局 ​

当你希望观察、保存或调整初始映射时,可以手动调用 fidelity_layout()。但后续 transpile()、to_instruction() 和 draw_time_scheduling() 仍应继续使用同一个 chip_backend。

python
from pyqpanda3.transpilation import Transpiler, decompose, fidelity_layout

decomposed = decompose(prog, ["U3", "CZ"])

init_mapping = fidelity_layout(
    decomposed,
    chip_backend.chip_topology_edges,
    chip_backend.single_gate_fidelity,
    chip_backend.readout_fidelity,
    chip_backend.double_gate_fidelity,
)
print("initial mapping:", init_mapping)

transpiled = Transpiler().transpile(
    decomposed,
    chip_backend,
    init_mapping,
    2,
)

instruction = transpiled.to_instruction(
    chip_backend,
    offset=1,
    is_scheduling=True,
    compensate_pulse=False,
)
figures = draw_time_scheduling(instruction, backend=chip_backend, output="plotly")

job = qcloud_backend.run_instruction([instruction], 1000, options)
print(type(figures).__name__)
print(job.result().get_counts_list())

示例输出形态:

text
initial mapping: {1: 106, 0: 96, 2: 115}
Figure
[{'000': 229, '001': 203, '010': 210, '011': 189, '100': 39, '101': 50, '110': 45, '111': 35}]

init_mapping 是 Python 字典,键是线路中的逻辑比特,值是芯片上的物理比特。

Fidelity Layout 的实现思路 ​

构建虚拟交互图 ​

布局过程会扫描分解后的程序。单比特门增加对应逻辑比特的重要性;测量让读出保真度参与评分;双比特门形成带权虚拟交互边,交互次数越多,权重越高。

搜索连通物理块 ​

芯片拓扑来自 chip_backend.chip_topology_edges。算法不会在整张芯片上盲目枚举所有排列,而是先根据线路使用的逻辑比特数量,在物理拓扑中寻找连通候选块。

为候选映射打分 ​

每个候选映射会根据以下因素计算综合错误代价:

  • 单比特门错误率:逻辑比特上的单比特操作越多,对应物理比特的单门保真度越重要。
  • 读出错误率:被测量的逻辑比特优先使用读出效果更好的物理比特。
  • 双比特门错误率:频繁交互的逻辑边优先放到高保真的物理 CZ 边上。
  • 拓扑距离惩罚:如果频繁交互的逻辑比特没有映射到相邻物理比特,会按距离增加惩罚。
text
cost =
  one_qubit_count  * single_gate_error(physical_qubit)
+ measure_count    * readout_error(physical_qubit)
+ two_qubit_count  * pair_cost(logical_edge, physical_qubits)

其中 pair_cost 取决于两个逻辑比特映射到的物理比特是否相邻:

  • 如果两个物理比特相邻,使用对应物理边的双门错误率。
  • 如果两个物理比特不相邻,则额外叠加非局域交互惩罚、距离惩罚和平均双门错误率。

缺失的保真度数据会使用同类已提供数据的平均错误率;如果该类数据完全为空,平均错误率为 0.0。

把初始映射交给 Routing ​

Fidelity layout 只决定初始映射,并不替代完整 routing。若初始映射已经把主要双比特交互放在相邻且高保真的物理边上,routing 阶段通常需要更少 SWAP;如果线路交互图和芯片拓扑差异较大,仍然可能需要 SWAP。

参数调优 ​

python
init_mapping = fidelity_layout(
    decomposed,
    chip_backend.chip_topology_edges,
    chip_backend.single_gate_fidelity,
    chip_backend.readout_fidelity,
    chip_backend.double_gate_fidelity,
    max_candidate_blocks=32,
    max_mappings_per_block=256,
    distance_penalty_weight=1.0,
)
参数说明
max_candidate_blocks候选物理块数量。增大后搜索更充分,但耗时更高。
max_mappings_per_block每个候选块中尝试的映射数量。增大后可能找到更好映射,但组合复杂度更高。
distance_penalty_weight拓扑距离惩罚权重。较大时更偏向减少 SWAP,较小时更偏向保真度。

运行完整示例 ​

源码包中包含可运行示例:

powershell
$env:QPANDA_QCLOUD_API_KEY="your_api_key"
$env:QPANDA_QCLOUD_BACKEND="WK_C180"
python samples/python/fidelity_layout_qcloud.py

如果不设置 QPANDA_QCLOUD_BACKEND,示例默认使用 WK_C180。

进阶:0.4.1 的保真度驱动近似与指标 ​

本教程聚焦 0.4.0 的 fidelity_layout() 位置参数工作流。0.4.1 在此基础上进一步让保真度数据驱动转译决策:

详见 转译教程 §4.5 和 转译选项与指标 API。

Released under the MIT License.