Qiskit 1.0.0升级指南:如何用transpile和run替换execute函数(附完整代码示例)

张开发
2026/6/30 4:47:03 15 分钟阅读
Qiskit 1.0.0升级指南:如何用transpile和run替换execute函数(附完整代码示例)
Qiskit 1.0.0升级实战从execute到transpile与run的平滑迁移量子计算开发者们注意了Qiskit 1.0.0版本的发布带来了API的重大变革其中最引人关注的莫过于execute函数的退役。这个曾经是我们量子电路执行万能钥匙的函数现在被更模块化的transpile和run组合所取代。本文将带你深入理解这一变化背后的设计哲学并提供可立即投入使用的迁移方案。1. 为什么Qiskit要弃用execute函数在Qiskit的早期版本中execute函数就像是一个黑盒子——你把量子电路丢进去它帮你处理所有事情电路优化、后端适配、作业提交。这种设计虽然方便初学者快速上手但却隐藏了量子计算工作流中的关键步骤导致开发者对底层过程缺乏控制。新版本将执行流程明确拆分为两个阶段transpile阶段负责电路的优化和适配特定后端run阶段处理实际的作业提交和结果获取这种分离带来了几个显著优势更精细的控制可以单独调整transpilation参数或运行参数更高的透明度清楚地知道电路在提交前经历了哪些转换更好的性能避免了每次执行都重复进行相同的transpilation# 旧版单步执行模式 result execute(circuit, backend, shots1000).result() # 新版两步执行模式 transpiled_circuit transpile(circuit, backend) result backend.run(transpiled_circuit, shots1000).result()2. 基础迁移从execute到transpilerun让我们从一个简单的量子电路开始展示如何将旧代码迁移到新API。假设我们有一个创建Bell态的电路from qiskit import QuantumCircuit from qiskit_aer import Aer # 创建量子电路 qc QuantumCircuit(2, 2) qc.h(0) qc.cx(0, 1) qc.measure([0, 1], [0, 1])2.1 旧版execute实现# 旧版代码Qiskit 1.0.0 backend Aer.get_backend(qasm_simulator) job execute(qc, backend, shots1024) result job.result() counts result.get_counts()2.2 新版transpilerun实现# 新版代码Qiskit ≥1.0.0 backend Aer.get_backend(qasm_simulator) # 第一步transpile电路 transpiled_qc transpile(qc, backend) # 第二步运行电路 job backend.run(transpiled_qc, shots1024) result job.result() counts result.get_counts()关键变化点execute函数被拆分为transpile和run两个独立调用run现在是后端对象的方法而不是全局函数transpile后的电路可以重复使用提高效率3. 高级迁移技巧与参数映射许多开发者在使用execute时会传递各种参数来控制电路执行。下面我们来看看这些参数在新API中如何映射execute参数新版位置注意事项shotsrun方法保持不变optimization_leveltranspile函数优化级别0-3initial_layouttranspile函数量子比特映射seed_simulatorrun的noise_model参数需要创建噪声模型coupling_maptranspile函数硬件拓扑约束# 带参数的复杂示例 backend Aer.get_backend(qasm_simulator) # transpile阶段参数 transpiled_qc transpile( qc, backend, optimization_level3, coupling_map[[0, 1], [1, 0]], initial_layout[0, 1] ) # run阶段参数 noise_model NoiseModel().from_backend(backend) job backend.run( transpiled_qc, shots5000, noise_modelnoise_model, seed_simulator42 )注意basis_gates参数现在也属于transpile阶段用于指定目标后端支持的基本门集合。4. 常见问题与调试技巧在迁移过程中开发者可能会遇到一些典型问题。以下是几个常见场景及其解决方案4.1 结果不一致问题现象迁移后结果统计与旧版不同原因transpile优化改变了电路结构解决方案比较transpile前后的电路print(f原始电路:\n{qc.draw()}) print(fTranspile后电路:\n{transpiled_qc.draw()})固定随机种子保证可重复性from qiskit.utils import algorithm_globals algorithm_globals.random_seed 424.2 性能下降问题现象同样的电路执行时间变长原因每次运行都重新transpile解决方案缓存transpile结果# 首次运行 transpiled_qc transpile(qc, backend) # 后续运行直接使用transpile结果 job backend.run(transpiled_qc, shots1000)4.3 自定义pass manager集成对于高级用户新版API提供了更灵活的pass manager集成方式from qiskit.transpiler import PassManager from qiskit.transpiler.passes import Unroller # 创建自定义pass manager pm PassManager([Unroller([u3, cx])]) # 应用自定义transpile transpiled_qc transpile(qc, backend, pass_managerpm)5. 实际项目迁移案例让我们看一个完整的项目迁移示例计算分子基态能量的VQE算法5.1 旧版实现from qiskit.algorithms import VQE from qiskit.algorithms.optimizers import SPSA from qiskit.circuit.library import TwoLocal from qiskit.opflow import PauliSumOp # 创建哈密顿量 hamiltonian PauliSumOp.from_list([(ZZ, 1.0), (II, -0.5)]) # 创建ansatz ansatz TwoLocal(2, rotation_blocksry, entanglement_blockscz) # 创建VQE实例 vqe VQE(ansatz, optimizerSPSA(), quantum_instancebackend) # 运行计算 result vqe.compute_minimum_eigenvalue(hamiltonian)5.2 新版实现from qiskit.algorithms.minimum_eigensolvers import VQE from qiskit.algorithms.optimizers import SPSA from qiskit.circuit.library import TwoLocal from qiskit.quantum_info import SparsePauliOp from qiskit.primitives import Estimator # 创建哈密顿量新版Operator格式 hamiltonian SparsePauliOp.from_list([(ZZ, 1.0), (II, -0.5)]) # 创建ansatz ansatz TwoLocal(2, rotation_blocksry, entanglement_blockscz) # 创建Estimator新版Primitives接口 estimator Estimator() # 创建VQE实例 vqe VQE(estimator, ansatz, SPSA()) # 运行计算 result vqe.compute_minimum_eigenvalue(hamiltonian)关键改进使用新的Primitives接口替代旧的QuantumInstanceOperator表示更改为SparsePauliOp算法接口更加模块化和可组合6. 迁移后的最佳实践完成API迁移后建议采用以下实践来提升代码质量和性能电路缓存对不变电路只transpile一次from functools import lru_cache lru_cache(maxsize32) def get_transpiled_circuit(circuit, backend): return transpile(circuit, backend)异步执行利用新版对异步的更好支持async def run_async(circuit, backend, shots): transpiled transpile(circuit, backend) job await backend.run(transpiled, shotsshots) return await job.result()性能分析使用transpile日志识别瓶颈import logging logging.basicConfig(levellogging.INFO) transpiled_qc transpile(qc, backend) # 查看详细优化日志自定义transpile针对特定硬件优化from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager pm generate_preset_pass_manager(3, backend) transpiled_qc pm.run(qc)在实际项目中我发现将transpile阶段与业务逻辑分离可以显著提高代码可维护性。通常我会创建一个专门的circuit_utils.py文件来集中处理所有与transpile相关的逻辑。

更多文章