编译、选项与区域选择 {#guide-compiler-options}¶
Important
本页所有 compile() / compile_with_config() / compile_for_backend() /
schedule_circuit() / plot_time_line_html() 调用都强制依赖 Qiskit。
任何 level(含 level=0)都会进入 Qiskit transpiler 路径,缺少 qiskit
时直接抛 CompilationFailedError。Qiskit 现在是 unified-quantum 的核心依赖,
随默认安装一起进来;如果 import qiskit 失败,说明环境损坏,请重装:
pip install --upgrade unified-quantum
只做线路构建、Circuit.qasm / Circuit.originir 导出、模拟器运行(含
Simulator / MPSSimulator / dummy:local:virtual-line-N)这些场景不需要
qiskit;只有进入”编译/调度/timeline”才需要。
什么时候进入本页 {#guide-compiler-options-when-to-read}¶
当你已经掌握线路构建和本地模拟的基础流程,并希望:
将线路编译到特定量子芯片的拓扑结构上
利用芯片的标定数据(各量子比特和门 fidelity)进行感知路由
使用类型化的后端选项替代手写
**kwargs根据芯片标定数据自动寻找最优物理量子比特区域
就应该进入本页。
本页涵盖三个相互独立又相互配合的新模块:
模块 |
文件 |
用途 |
|---|---|---|
增强编译 ( |
|
Qiskit 感知路由 + 多格式输出 |
后端选项 ( |
|
类型化后端选项 |
区域选择器 ( |
|
最优量子比特区域发现 |
1. 增强编译:compile() 函数¶
1.1 为什么需要 compile()?¶
现有的 transpile_originir() / transpile_qasm() 返回字符串,缺少:
芯片标定感知路由:根据各量子比特 fidelity 选择高保真路径
统一的返回类型:可返回
Circuit对象而非字符串编译元数据:SWAP 插入数量、预估成功率
compile() 是这三个问题的统一解决方案。
1.2 核心签名¶
from uniqc.compile import compile
from uniqc import TranspilerConfig
# 最简用法
compiled = compile(circuit, backend_info=backend_info)
# 完整参数
compiled = compile(
circuit, # Circuit 对象或 OriginIR 字符串
backend_info=backend_info, # 提供拓扑图(可选,有 ChipCharacterization 时可省略)
level=2, # Qiskit 优化级别 0–3,默认 2
basis_gates=["cz", "sx", "rz"], # 目标基门集,默认 ["cz", "sx", "rz"]
chip_characterization=chip, # 芯片标定数据(可选)
output_format="circuit", # "circuit" | "originir" | "qasm",默认 "circuit"
)
1.3 拓扑来源优先级¶
compile() 拓扑来源优先级:
1. backend_info.topology (明确指定 BackendInfo)
2. chip_characterization.connectivity (从芯片标定获取)
3. ValueError (两处都没有则抛出异常)
1.4 输出格式¶
# 返回 Circuit 对象(推荐)
circ = compile(circuit, backend_info=info, output_format="circuit")
assert isinstance(circ, Circuit)
# 返回 OriginIR 字符串
oir = compile(circuit, backend_info=info, output_format="originir")
assert "QINIT" in oir
# 返回 OpenQASM 2.0 字符串
qasm = compile(circuit, backend_info=info, output_format="qasm")
assert "OPENQASM" in qasm
1.5 TranspilerConfig:类型化配置(可选)¶
TranspilerConfig 是一个 frozen=True 的数据类,可用于打包并复用一组编译参数(便于缓存、传参)。注意:compile() 当前不直接接受 config 参数,调用时需要把字段展开传入:
from uniqc import TranspilerConfig, compile, find_backend
config = TranspilerConfig(
type="qiskit", # 目前仅支持 "qiskit",预留扩展
level=3, # 最强优化
basis_gates=["cz", "sx", "rz"], # 自定义基门集
chip_characterization=chip, # 传入标定数据以启用感知路由
)
backend_info = find_backend('originq:WK_C180')
compiled = compile(
circuit,
backend_info,
type=config.type,
level=config.level,
basis_gates=config.basis_gates,
chip_characterization=config.chip_characterization,
)
compile() 总是直接返回 Circuit(或字符串,取决于 output_format)。需要拿到 SWAP 数量、估算成功率等编译元数据时,请使用内部 API compile_full(),它返回 CompilationResult(注意:compile_full 与 CompilationResult 当前未在公开命名空间暴露)。
1.6 芯片标定感知路由¶
当传入 chip_characterization 时,compile() 内部会:
构建加权图,边权重 =
1 - fidelity(低权重 = 高保真)对每个不满足拓扑的 2Q 门,用 Dijkstra 找最高保真路径
在路径上插入 SWAP 门
返回插入的 SWAP 数量和预估电路成功率
from uniqc.backend_adapter.task.adapters.originq_adapter import OriginQAdapter
adapter = OriginQAdapter()
chip = adapter.get_chip_characterization("WK_C180")
compiled = compile(
circuit,
chip_characterization=chip,
output_format="circuit",
)
# 内部自动使用 chip.two_qubit_data 中的 fidelity 数据选择路由路径
1.7 与现有 API 的关系¶
transpile_originir(circuit_str, backend_info)
↓ 返回 str(OriginIR)
↓
compile(circuit, backend_info)
↓ 返回 Circuit | str
↓ 两函数并存,compile() 为推荐入口
transpile_qasm(qasm_strs, ...)
↓ 返回 str(QASM)
compile() 不替代 现有函数,而是提供更高层的统一入口。现有 transpile_originir() 和 transpile_qasm() 保持不变。
2. 类型化后端选项:BackendOptions¶
2.1 为什么需要 BackendOptions?¶
现有 submit_task(circuit, "originq:WK_C180", shots=1000, measurement_amend=True) 的问题:
无 IDE 自动补全:字符串参数无法提供类型提示
无文档注解:不知道有哪些可选参数
平台间不一致:各平台参数名不同,无法统一处理
BackendOptions 在保留 **kwargs 兼容性的同时,提供了类型安全的替代接口。
2.2 类层次结构¶
BackendOptions(基类)
├── OriginQOptions
├── IBMOptions
└── DummyOptions
2.3 各平台选项¶
OriginQ¶
from uniqc import OriginQOptions
opts = OriginQOptions(
backend_name="originq:WK_C180", # OriginQ 后端名(canonical 'provider:chip' 形式)
circuit_optimize=True, # 默认 True,后端执行时优化
measurement_amend=False, # 默认 False,测量误差缓解
auto_mapping=False, # 默认 False
shots=1000, # 继承自 BackendOptions 基类
)
IBM¶
from uniqc import IBMOptions
opts = IBMOptions(
chip_id="ibm_kyoto", # 可选,不填则使用 IBM 默认后端
auto_mapping=True, # 默认 True
circuit_optimize=True, # 默认 True
task_name="ibm-task", # 可选
shots=1000,
)
Dummy(本地模拟器)¶
from uniqc import DummyOptions
opts = DummyOptions(
noise_model=None, # 可选,传入噪声模型进行噪声模拟
available_qubits=16, # 默认 16
available_topology=None, # 可选,指定拓扑 [[u,v], ...],None=all-to-all
shots=1000,
)
2.4 BackendOptionsFactory:工厂模式¶
from uniqc import BackendOptionsFactory, OriginQOptions
# 从 kwargs dict 构建
opts = BackendOptionsFactory.from_kwargs("originq", {
"backend_name": "originq:WK_C180",
"circuit_optimize": False,
})
assert isinstance(opts, OriginQOptions)
# 从 dict 规范化(normalize_options 的主入口)
opts = BackendOptionsFactory.normalize_options(
{"backend_name": "originq:WK_C180"}, "originq"
)
2.5 与 submit_task() 集成¶
from uniqc import submit_task, OriginQOptions
# 方式 1:直接传入 BackendOptions 实例(推荐)
opts = OriginQOptions(backend_name="originq:WK_C180", shots=2000)
task_id = submit_task(circuit, "originq:WK_C180", options=opts)
# 方式 2:传入 dict(底层自动转换为 BackendOptions)
task_id = submit_task(circuit, "originq:WK_C180", shots=500, options={
"measurement_amend": True,
})
# 方式 3:纯 kwargs(向后完全兼容,无变化)
task_id = submit_task(circuit, "originq:WK_C180", shots=500,
measurement_amend=True,
)
向后兼容性保证:当 options=None 且没有平台特定 kwargs 时,函数行为与之前完全相同。options 参数是纯增量的。
3. 区域选择器:RegionSelector¶
3.1 为什么需要 RegionSelector?¶
量子芯片上的物理量子比特具有不同的门保真度(由标定数据表征)。对于一个需要 N 个量子比特的电路,选择哪 N 个量子比特会直接影响执行成功率。
RegionSelector 通过分析 ChipCharacterization 标定数据,自动找到:
最高保真度的线性链(1D)
适合给定电路的 2D 区域
3.2 初始化¶
from uniqc.backend_adapter.task.adapters.originq_adapter import OriginQAdapter
from uniqc import RegionSelector
adapter = OriginQAdapter()
chip = adapter.get_chip_characterization("WK_C180")
selector = RegionSelector(chip)
3.3 find_best_1D_chain:寻找最优线性链¶
适用于线性拓扑电路(如 GHZ 态、线性葡萄串结构)。
from uniqc import ChainSearchResult
# 在全芯片上找最优 5-qubit 链
result = selector.find_best_1D_chain(5)
print(f"最优链: {result.chain}") # e.g. [0, 1, 2, 3, 4]
print(f"预估成功率: {result.estimated_fidelity:.4f}") # e.g. 0.9405
print(f"所需 SWAP 门数: {result.num_swaps}")
# 指定起始量子比特(强制从某处开始)
result = selector.find_best_1D_chain(4, start=2)
# → 从 qubit 2 开始的最优 4-qubit 链
# 无法达到精确长度时,返回最长可用链
result = selector.find_best_1D_chain(100) # 芯片只有 10 个 qubit
print(f"最长链: {result.chain}") # 返回全芯片最长路径
# 控制搜索超时(默认 30 秒,大芯片上可适当放宽)
result = selector.find_best_1D_chain(20, max_search_seconds=60.0)
# 超时后返回当前找到的最优结果(可能是部分链)
算法说明:
贪心扩展:从起始量子比特出发,每次选择 fidelity 最高的邻居
DFS 回溯:若贪心陷入死路,用带剪枝的深度优先搜索找最长路径
保真度计算:
F = \prod fidelity(edge_i),即所有边 fidelity 的乘积
3.4 find_best_2D_from_circuit:寻找最优 2D 区域¶
适用于需要 2D 连接的电路(如量子游走、VQE ansatz)。
from uniqc import RegionSearchResult
# 从芯片标定数据中找最适合 circuit 的 2D 区域
result = selector.find_best_2D_from_circuit(
circuit,
min_qubits=4, # 覆盖电路所需最小量子比特数(可覆盖)
max_region_size=36, # 最大搜索范围(默认 36,对应 6×6)
max_search_seconds=10.0, # 搜索超时(防止大芯片搜索爆炸)
transpiler=None, # 可选:传入 fidelity 评估函数
)
print(f"最优区域: {result.qubits}")
print(f"区域形状: {result.region_shape}") # e.g. (2, 3)
print(f"预估成功率: {result.estimated_fidelity:.4f}")
算法说明:
解析电路的量子比特需求(
max(circuit.max_qubit + 1, circuit.qubit_num))枚举矩形子图:尝试 1×N, 2×N, 3×N, … 形状的连通子图
用
estimate_circuit_fidelity()对每个候选区域打分返回预估成功率最高的区域
3.5 estimate_circuit_fidelity:电路保真度估算¶
基于乘积保真度公式:
P_success = \prod(1Q gate fidelity) \times \prod(2Q gate fidelity) \times \prod(readout fidelity)
# 对全芯片所有量子比特估算
fid = selector.estimate_circuit_fidelity(circuit)
# 对特定量子比特子集估算
fid = selector.estimate_circuit_fidelity(circuit, qubits={0, 1, 2, 3})
# 与 RegionSelector 配合使用
result = selector.find_best_2D_from_circuit(circuit, min_qubits=4)
if result.qubits:
fid = selector.estimate_circuit_fidelity(circuit, qubits=result.qubits)
print(f"最优区域预估成功率: {fid:.4f}")
缺失数据处理:当某量子比特或边不在标定数据中时,默认使用 0.99 fidelity(即 1% 错误率)。这避免了对部分标定芯片返回 0 的问题。
3.6 辅助方法¶
# 获取所有量子比特按单门 fidelity 排名
rankings = selector.get_qubit_rankings()
# → [(qubit_id, fidelity), ...],按 fidelity 降序
# 获取所有边按 2Q 门 fidelity 排名
edge_rankings = selector.get_edge_rankings()
# → [((qubit_u, qubit_v), fidelity), ...]
4. 组合使用示例¶
4.1 完整流水线:RegionSelector → compile → submit_task¶
from uniqc import (
RegionSelector,
OriginQOptions,
submit_task,
BackendOptionsFactory,
)
from uniqc.backend_adapter.task.adapters.originq_adapter import OriginQAdapter
from uniqc.compile import compile
from uniqc import Circuit
# 1. 构建电路
circuit = Circuit()
for i in range(5):
circuit.h(i)
for i in range(4):
circuit.cnot(i, i + 1)
circuit.measure(*range(5))
# 2. 获取芯片标定
adapter = OriginQAdapter()
chip = adapter.get_chip_characterization("WK_C180")
# 3. 找最优量子比特区域
selector = RegionSelector(chip)
region = selector.find_best_2D_from_circuit(circuit, min_qubits=5)
print(f"最优执行区域: {region.qubits}")
# 4. 将电路编译到该区域
compiled = compile(
circuit,
chip_characterization=chip,
output_format="circuit",
)
print(f"编译后电路: {compiled.originir[:100]}...")
# 5. 提交任务
opts = OriginQOptions(shots=1000)
task_id = submit_task(compiled, "originq:WK_C180", options=opts)
print(f"任务 ID: {task_id}")
5. API 速查¶
compile()¶
参数 |
类型 |
默认值 |
说明 |
|---|---|---|---|
|
|
— |
输入电路 |
|
|
|
提供拓扑信息 |
|
|
|
Qiskit 优化级别 0–3 |
|
|
|
目标基门集 |
|
|
|
标定数据(启用感知路由) |
|
|
|
输出格式 |
OriginQOptions¶
字段 |
类型 |
默认值 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RegionSelector¶
方法 |
说明 |
|---|---|
|
找最优 |
|
找最适合电路的 2D 区域 |
|
估算电路在给定量子比特上的成功率 |
|
按 fidelity 排名所有量子比特 |
|
按 2Q fidelity 排名所有边 |
常见错误¶
缺少 Qiskit 依赖
调用 compile() 时若 Qiskit 未安装,会抛出 CompilationFailedError。Qiskit 是核心依赖,缺失时通常意味着安装损坏,重装即可:
pip install --upgrade unified-quantum
绘图功能需要 matplotlib
plot_time_line() 需要 matplotlib。若未安装,调用时返回 None 而不抛异常。若需脉冲序列可视化:
pip install matplotlib
Note
🔧 schedule_circuit 与 plot_time_line* 在内部始终调用 compile()(默认
compile_to_basis=True),即便输入只使用平台原生门也不例外。因此它们强制依赖
Qiskit;qiskit 现在是 unified-quantum 的核心依赖,缺失时请重装:
pip install --upgrade unified-quantum
唯一可绕过 compile() 的路径是:构造一份所有 entry 都已带 start_time 的 pulse /
timeline 数据,并显式传 compile_to_basis=False(否则会抛 TimelineDurationError)。