pyqpanda3 v0.4.0 把硬件工作流的"链路"打通了:从云端芯片元数据到保真度布局、指令导出和时序可视化。v0.4.1 想解决的是这条链路里更靠"内核"的一层问题——当后端已经能给出保真度数据时,转译器有没有真的用它来做决策?
答案是:现在有了。本版本的主题是让保真度数据真正贯穿到转译决策里,同时补齐两类长期缺失的模拟器。
强类型转译选项与指标回收
0.4.0 的 transpile() 用位置参数控制优化等级与布局策略。0.4.1 新增 TranspilationOptions,把所有可调项集中到一个对象里,并通过 TranspilationResult 一次性返回转译后的程序、编译耗时和指标。
from pyqpanda3.core import QProg, H, CZ, measure
from pyqpanda3.transpilation import (
ChipBackend,
LayoutMethod,
RoutingMethod,
Transpiler,
TranspilationOptions,
)
prog = QProg()
prog << H(0) << CZ(0, 1) << measure(0, 0) << measure(1, 1)
backend = ChipBackend()
backend.chip_topology_edges = [[0, 1], [1, 2]]
backend.basic_gates = ["RPhi", "CZ"]
backend.single_gate_fidelity = {0: 0.99, 1: 0.99, 2: 0.99}
backend.readout_fidelity = {0: 0.90, 1: 0.90, 2: 0.99}
backend.double_gate_fidelity = {(0, 1): 0.90, (1, 2): 0.99}
options = TranspilationOptions()
options.optimization_level = 2
options.layout_method = LayoutMethod.FIDELITY
options.routing_method = RoutingMethod.LIGHT_SABRE
options.approximation_degree = 0.99
options.execution.routing_trials = 8
options.execution.seed = 42
result = Transpiler().transpile(prog, backend, options)
print(type(result).__name__)
print(result.compile_time_ns > 0)
print(sorted(result.metrics.keys()))示例输出形态:
TranspilationResult
True
['depth', 'fidelity_exact', 'fidelity_fallback', 'fidelity_unknown', 'log_expected_fidelity', 'two_qubit_gate_count']result.metrics 与独立函数 transpilation_metrics(prog, backend) 返回的字典结构一致,包含双比特门数量、深度、对数期望保真度,以及保真度数据精确命中 / 回退 / 未知的门数计数。这意味着转译质量终于可以量化、可比对,而不仅仅是"跑通了"。
LightSABRE 路由
RoutingMethod.LIGHT_SABRE(字符串 "light_sabre")启用新的分层前瞻路由器。它在路由时按层扩展交互图,能减少双比特门插入与交换深度,适合耦合度受限或线路较深的后端。
from pyqpanda3.core import QProg, H, CZ, measure
from pyqpanda3.transpilation import ChipBackend, Transpiler
prog = QProg()
prog << H(0) << CZ(0, 1) << measure(0, 0) << measure(1, 1)
backend = ChipBackend()
backend.chip_topology_edges = [[0, 1], [1, 2]]
backend.basic_gates = ["RPhi", "CZ"]
transpiled = Transpiler().transpile(
prog,
backend,
{},
2,
"fidelity",
"light_sabre",
"default",
approximation_degree=0.99,
)
print(type(transpiled).__name__)
print(len(transpiled.operations()) > 0)输出:
QProg
True海森堡绘景期望模拟器
很多场景下,你并不需要完整的态矢量,而只想知道某个泡利哈密顿量的期望值 <H>。SparseHeisenbergSimulator 在海森堡绘景里直接算这件事,不用采样、也不返回态矢量,因此对"受支持门集 + 直积初态"这类问题远比完整模拟便宜。
from pyqpanda3.core import QProg, CZ, SparseHeisenbergSimulator
zero = (1 + 0j, 0 + 0j) # 每个比特的 (|0> 振幅, |1> 振幅)
prog = QProg() << CZ(0, 1) # |00> 不变
sim = SparseHeisenbergSimulator(num_qubits=2)
sim.set_initial_product_state([zero, zero])
sim.add_observable("ZZ", 1.0)
sim.evolve_backward(prog)
print(round(sim.expectation(), 6))输出:
1.0<ZZ> 在 |00> 上为 1.0,与解析值一致。当算符项数膨胀时,可以用 max_terms 与 truncation_norm="l1" 截断,并通过 stats() 看被丢弃的项。
矩阵乘积态(MPS)模拟器
MPSQVM 用矩阵乘积态后端运行量子程序,对纠缠较弱的线路在比特数较大时仍保持较低内存占用。
from pyqpanda3.core import H, MPSQVM, QProg, measure
prog = QProg() << H(0) << measure(0, 0) << measure(1, 1)
qvm = MPSQVM()
qvm.run(prog, 1000)
result = qvm.result()
print(type(result).__name__)
print(sum(result.get_counts().values()) == 1000)示例输出形态:
QResult
True还有这些值得注意
state_fidelity()进入quantum_info,支持密度矩阵与态矢量四种组合,填补了"直接比较两个量子态"的空白。Choi、SuperOp、PTM三个信道表示都补上了ndarray(),方便与 NumPy 生态对接。QProg.get_measure_qubits_cbits()按程序顺序返回测量对,便于在提交云端前核对测量映射。- 一批稳定性修复:
VQCircuit.append(vqc)自引用段错误、VF2 布局部分覆盖段错误、ParamExpression空表达式崩溃、退相干噪声 Kraus 矩阵方向、get_matrix内存泄漏、PartialAmplitudeQVM下标越界校验。
0.4.1 后半程:初态、Heisenberg 与任务取消
v0.4.1 的功能在发布周期里分两批合入:前半程是保真度驱动的转译链路与两个模拟器,后半程又补上了模拟器的初态控制、海森堡绘景的截断统计,以及云端任务取消。
初态:CPUQVM.init_state
CPUQVM 在 0.4.1 新增 init_state(state):运行前把模拟器设置到任意初始态,无参调用则恢复默认的 |0...0>。例如把两个比特放在叠加态上再测量:
import numpy as np
from pyqpanda3.core import CPUQVM, QProg, measure
qvm = CPUQVM()
qvm.init_state([1 / np.sqrt(2), 0, 0, 1 / np.sqrt(2)])
prog = QProg() << measure([0, 1], [0, 1])
qvm.run(prog, 1000)
print(qvm.result().get_counts())
qvm.init_state() # 恢复默认 |0...0>
qvm.run(prog, 1000)
print(qvm.result().get_counts())示例输出形态:
{'00': 524, '11': 476}
{'00': 1000}注意:MPSQVM 的 C++ init_state 未在 Python 绑定中暴露(0.4.1),Python 侧请使用 CPUQVM.init_state。
海森堡绘景的截断与统计
前面提到 SparseHeisenbergSimulator 可以用 max_terms 与 truncation_norm 截断。实际效果如何?RX 旋转会把算符项数从 1 膨胀到 8,设 max_terms=4 后多余的项按 l1 范数丢弃,stats() 给出被丢弃项的统计:
from pyqpanda3.core import QProg, H, CNOT, RX, SparseHeisenbergSimulator
zero = (1 + 0j, 0 + 0j)
prog = QProg() << H(0) << CNOT(0, 1) << RX(0, 0.7) << RX(1, 1.3) << RX(2, 2.1)
# 不截断:观察算符项数膨胀到多少
full = SparseHeisenbergSimulator(num_qubits=3)
full.set_initial_product_state([zero, zero, zero])
full.add_observable("ZZZ", 1.0)
full.evolve_backward(prog)
print("no truncation terms:", full.stats().active_terms)
# 截断:最多保留 4 项,多余项按 l1 范数丢弃
trunc = SparseHeisenbergSimulator(num_qubits=3, max_terms=4, truncation_norm="l1")
trunc.set_initial_product_state([zero, zero, zero])
trunc.add_observable("ZZZ", 1.0)
trunc.evolve_backward(prog)
s = trunc.stats()
print("expectation:", round(trunc.expectation(), 6))
print("active_terms:", s.active_terms)
print("truncated_terms:", s.truncated_terms)
print("truncated_l1:", round(s.truncated_l1, 6))
print("coefficient_l1:", round(s.coefficient_l1, 6))输出:
no truncation terms: 8
expectation: 0.400378
active_terms: 4
truncated_terms: 4
truncated_l1: 0.51565
coefficient_l1: 2.373074云端任务取消
QCloudJob 新增 cancel() 与静态方法 cancel_task(task_id),可以主动取消已提交的云端任务,返回 True 表示云服务接受了取消请求。取消需要云端凭据与真实任务,无法本地执行:
from pyqpanda3.qcloud import QCloudJob, QCloudService
# 需云端凭据与真实任务,无法本地执行
service = QCloudService("your_api_key")
job = QCloudJob("your_job_id")
print(job.cancel()) # 取消当前任务
print(QCloudJob.cancel_task("your_task_id")) # 按任务 id 取消(静态方法)完整的 API 变更清单见 v0.4.1 发布说明。