线路执行与工具流程
概述
本页整合了线路执行、结果查看、线路分析与绘图、以及 OpenQASM 导入导出的核心用法,适合作为完整工作流的快速参考。
执行线路与查看结果
普通用户直接调用 Circuit.execute(),返回 ExecutionResult 对象:
from unitarylab import Circuit
qc = Circuit(2)
qc.h(0)
qc.cx(0, 1)
result = qc.execute()ExecutionResult 核心字段与方法
result.state:最终状态向量,只读的一维 NumPy 数组(每次访问都会从后端状态实时转换,不做缓存)。result.backend_state:底层后端原始状态对象(如 GPU 上的 torch 张量),未做设备拷贝,性能敏感场景可直接使用。result.probabilities:全部计算基态的概率分布字典,键为 little-endian 二进制字符串,值为对应概率。result.probability(bitstring, qubits=None):查询单个计算基态结果的概率。result.marginal_probabilities(qubits=None, threshold=1e-12):指定子集比特的边际概率分布。result.sample(shots=1, qubits=None, seed=None):不坍缩状态,按概率分布采样若干计算基态结果,返回字符串列表。result.expectation(observable, qubits=None):计算可观测量期望值 ,支持"Z"、"XX"、完整长度 Pauli 串、或(系数, 算符, 比特)项列表等多种输入形式。result.measure(target_indices, seed=None):对指定比特执行投影测量并坍缩内部状态,返回测量结果字符串;这个种子独立于Circuit.execute(seed=...)。result.classical_results_map:经典比特索引到测量值(0或1)的字典,仅在线路中添加了measure操作后才有值。result.shots/result.counts/result.classical_registers:分别为本次执行的 shots 数、跨 shots 汇总的经典比特串计数、按寄存器名分组的最后一次 shot 测量结果。
print(result.state)
# [0.70710678+0.j 0.+0.j 0.+0.j 0.70710678+0.j]
print(result.probabilities)
# {'00': 0.4999..., '11': 0.4999...}
print(result.expectation("ZZ", qubits=(0, 1)))
# Bell 态下 ZZ 期望值应接近 1(两比特完全关联)后端、设备与执行参数
execute() 支持 backend、device、dtype、shots、seed、backend_options 参数:
result = qc.execute(backend='torch', device='cpu')| 参数组合 | 适用场景 |
|---|---|
backend='torch', device='cpu'(默认) | 适合大多数情况 |
backend='torch', device='gpu' | 有 GPU 时加速(仅 torch 支持 gpu) |
backend='numpy', device='cpu' | 纯 NumPy 环境 |
backend='cpp', device='cpu' | 使用编译的 C++ 门核加速 CPU 执行 |
backend='tensornet', device='cpu' | 大比特数、低纠缠线路,使用 MPS 表示 |
通常直接调用 qc.execute() 无需指定参数;模拟大线路且有 GPU 时可指定 device='gpu';比特数很大但纠缠有限时可尝试 backend='tensornet' 并通过 backend_options 控制 max_bond/cutoff/routing。seed 默认固定为 42(结果可复现),需要真正随机采样时传 seed=None。参数完整说明见 快速开始 与 核心线路接口。
线路分析与绘图
draw()
qc.draw() # 弹出图窗(默认 output='mpl')
qc.draw(filename='circuit.png') # 保存为文件
qc.draw(filename='circuit.png', title='Bell State') # 添加标题
qc.draw(output='text') # 纯文本线路图
qc.draw(output='latex') # LaTeX(quantikz)线路图
qc.draw(compact=False) # 关闭相邻单比特门合并在 Jupyter Notebook 中图形会内联显示,在普通脚本中会弹出独立窗口。output 支持 'mpl'(默认,Matplotlib)、'text'、'latex' 三种模式,分别对应内部的 MatplotlibCircuit、TextCircuitDrawer、LatexCircuitDrawer。
CircuitInfo
CircuitInfo 提供线路静态分析,可通过 qc.analyze() 快捷调用:
from unitarylab.circuit_analysis import CircuitInfo
info = CircuitInfo(qc) # 等价于 info = qc.analyze(show=False)
info.show() # 打印概览、指令列表、层结构常用方法:
| 方法 | 说明 |
|---|---|
size() | 门总数 |
depth() | 线路深度(串行最长路径,考虑门间数据依赖,不是门总数) |
count_ops() | 各门类型出现次数,返回 dict |
count_single_qubit_gates() / count_two_qubit_gates() / count_multi_qubit_gates() | 按比特数分类的门计数 |
count_parameterized_gates() | 带参数(旋转角等)的门数量 |
get_qubit_usage() | 各量子比特的操作次数 |
get_coupling_map() | 量子比特耦合关系(双比特门连接对),例如 [(0, 1), (1, 2)] |
get_qubit_history(qubit) | 指定比特的完整操作历史 |
get_instructions() / get_layers() / get_parameters() | 分别返回指令列表、按层分组的门、参数化门的参数汇总 |
is_parameterized() | 线路是否包含参数化门 |
get_summary() / to_dict() | 结构化概览 / 将分析结果整体导出为字典 |
show(sections=None, qubit=None) | 按章节打印分析结果 |
show() 支持的 sections 值:'overview'(或别名 'summary')、'instructions'、'layers'、'qubit_usage'、'coupling_map'、'parameters'、'qubit_history'(需同时指定 qubit= 参数)。不传 sections 时默认打印 ['overview', 'instructions', 'layers']。
info.show(sections=['overview', 'coupling_map'])
info.show(sections='qubit_history', qubit=0)OpenQASM 导入导出
OpenQASM 2.0 / 3.0 均受支持,适合保存、交换线路,或与其他工具互操作。公开方法与参数速查见 核心线路接口;这里重点说明底层接口和兼容性限制。
# 使用前文已经构建的 qc;默认导出 OpenQASM 3.0
qasm3_str = qc.to_qasm()
qasm2_str = qc.to_qasm2()
# 导入(自动识别 2.0 / 3.0)
qc2 = Circuit.from_qasm(qasm3_str)底层函数(高级用法)
Circuit.to_qasm() / from_qasm() 内部委托给 unitarylab.backend.qasm 模块的一组函数,直接操作 GateSequence 而非 Circuit。仅在需要脱离 Circuit 单独处理 GateSequence,或需要显式指定寄存器结构时才需要直接调用:
from unitarylab.backend.qasm import (
gate_sequence_to_qasm, # 统一入口,默认导出 QASM 3.0
gate_sequence_to_qasm2,
gate_sequence_to_qasm3,
gate_sequence_from_qasm, # 统一入口,自动识别版本
qasm2_to_gate_sequence,
qasm3_to_gate_sequence,
circuit_from_gate_sequence, # 将 GateSequence 重建为 Circuit
)
qasm_str = gate_sequence_to_qasm3(qc.gate_sequence, qreg_name='q')
gs = qasm3_to_gate_sequence(qasm_str)
qc3 = circuit_from_gate_sequence(Circuit, gs)支持范围与限制
支持的门包括:x、y、z、h、s、sdg、t、tdg、rx、ry、rz、p、U(unitary)、cx、swap,以及受控门修饰符(ctrl @、negctrl @)和自定义 gate 定义。
主要限制:
- 同时支持 OpenQASM 2.0 和 3.0,默认导出/自动识别均以 3.0 为准;需要 2.0 时显式调用
to_qasm2()/gate_sequence_to_qasm2()。 - 门参数必须是数值,不支持符号表达式(如
pi/2会被数值化)。 - 不支持经典控制流(
if、while等)。 - 并非所有自定义门都能完整往返导出;非连续块门会内联展开。
- 携带矩阵信息的
unitary门(即通过qc.unitary(matrix, target)添加、g.matrix属性非空的门)会以 UnitaryLab 扩展语句形式导出(矩阵元素编码为交替的实部/虚部参数),并可通过from_qasm()完整还原——这是 UnitaryLab 专属扩展,并非标准 OpenQASM 3.0 互操作格式,若目标是导入第三方工具,仍建议先transpile()。只有当unitary门的矩阵信息缺失(g.matrix is None,一般出现在部分中间处理路径)时,to_qasm()才会抛出NotImplementedError并在错误信息中给出重试建议(transpile=True或decompose=True, transpile=True)。
综合示例
以下是一个包含执行、查看结果、分析、绘图和导出 OpenQASM 的最小完整示例:
from unitarylab import Circuit
# 1. 创建 Bell 线路
qc = Circuit(2)
qc.h(0)
qc.cx(0, 1)
# 2. 执行线路
result = qc.execute()
# 3. 查看概率
print(result.probabilities)
# {'00': 0.4999..., '11': 0.4999...}
# 4. 线路分析
qc.analyze(show=True, sections=["summary"])
# 5. 绘图
qc.draw(title="Bell State")
# 6. 导出 OpenQASM 3.0(详细说明见上文)
qasm_str = qc.to_qasm()注意事项
- Qubit 顺序:
probabilities的键为 little-endian 二进制字符串,最低有效位对应 qubit 0。 - 投影测量会坍缩状态:
result.measure()会修改内部状态(投影坍缩)。如需在同一个未坍缩状态上重复查询不同子系统的分布,使用result.marginal_probabilities()或result.sample(),它们都不会修改result.state;只有result.measure()会坍缩。 - GPU 与后端:默认设置适用于大多数场景,仅在性能调优时需要调整
backend、device、dtype、backend_options。 - MDX 特殊字符:在 MDX 文件中,表格单元格内容中的
|应写为|;{}、\等特殊字符应放入代码块或行内代码。