量子底层控制:脉冲级编程与 OpenPulse

系统讲解量子底层控制与脉冲级编程:从门级到脉冲级为什么要下探、脉冲的物理描述(复数包络、I/Q 调制、dt 时间单位与采样率)、OpenPulse 的核心概念(Schedule、pulse、Play、ShiftPhase、SetFrequency、Acquire)、用 Qiskit Pulse 实现自定义门与 DRAG 拖尾校正、测量与采集(measure、acquire、kernel)、校准实验编排、硬件限制(带宽、串扰、泄漏到 |2⟩)、与门级编译的关系,以及平台支持与迁移到 Qiskit 1.x/2.x 的变化。

引言

绝大多数量子编程都停留在「门级」:写 qc.h(0)、qc.cx(0, 1),然后交给编译器。但在编译器之下,还有一层更接近硬件的东西——脉冲。每个门最终都被翻译成一条微波脉冲,脉冲的包络形状、振幅、相位、频率共同决定了这次操作的保真度。当你需要把单门保真度从 99.9% 推到 99.99%,或者实现一个标准门库里没有的操作时,就必须下探到这一层。

OpenPulse 是 Qiskit 为这一层提供的编程接口:它让你直接描述「在哪个通道上、什么时刻、播放什么形状的脉冲」。本文系统讲解脉冲级编程:先从「为什么要下探」讲起,再讲脉冲的物理描述与 OpenPulse 的核心概念,然后是自定义门、DRAG 校正、测量采集、校准实验编排、硬件限制,最后讨论与门级编译的关系以及 Qiskit 版本迁移。目标:让你既能读懂 backend.defaults() 里的脉冲定义,也能自己写出一个自定义门。

前置:量子比特校准与噪声表征 、Qiskit 编程入门 、量子比特与门基础 。


目录


1. 从门级到脉冲级

门级抽象的局限:

门级视角:qc.x(0) 就是「一个 X 门」
但硬件实际执行的是:
  在 DriveChannel(0) 上播放一条时长为 d、振幅为 A 的复数脉冲
  A 与 d 共同决定旋转角 θ = Ω_R · d
→ 门级隐藏了「用哪条脉冲实现」的自由度

下探到脉冲级的三个动机:

1. 更短的电路
   多个相邻门可合并成一条脉冲(如 Rz 可虚拟化、相位可累加)
   → 减少脉冲数量、缩短总时长

2. 更高的保真度
   调整包络形状(DRAG、高斯平方、slepian)压制泄漏与串扰
   → 单门保真度可从 99.9% 推到 99.99%

3. 校准与误差缓解
   直接编排 Rabi / Ramsey / RB 等校准实验
   自定义读出脉冲以优化信噪比
→ 这三条构成了「脉冲级编程」的全部价值

层次从高到低是:门级(QuantumCircuit,算法开发者写电路)、编译级(transpile,编译器做映射与优化)、脉冲级(Schedule / OpenPulse,硬件与校准工程师做自定义门与校准)、仪器级(AWG 与采集卡,实验室控制波形、采样与触发)。

心智:门级是「面向算法」的抽象,脉冲级是「面向硬件」的抽象——下探的理由只有三个:更短的电路、更高的保真度、更灵活的校准。若你的目标只是跑通算法,不必下探;若你要压榨保真度或实现门库外的操作,脉冲级是必经之路。


2. 脉冲的物理描述

脉冲 = 复数包络 × 载波:

物理输出信号:
  s(t) = Re{ A(t) · e^(i(ω_d t + φ)) }
       = I(t)·cos(ω_d t) - Q(t)·sin(ω_d t)
  A(t) 是复数包络:A(t) = I(t) + i·Q(t)
  ω_d 是驱动频率,φ 是初始相位

旋转坐标系下,脉冲的作用等价于:
  H(t) = (Ω(t)/2)·[cos(φ)σ_x + sin(φ)σ_y]
  Ω(t) ∝ |A(t)|,旋转轴由 φ 决定
→ 包络的「面积」∫Ω(t)dt 决定总旋转角

dt 时间单位与采样率:

硬件以固定采样率输出波形,最小时间单位为 dt
  典型 dt ≈ 0.222 ns(对应采样率 4.5 GSa/s)
  → 脉冲时长必须是 dt 的整数倍

换算:
  duration = 160(单位 dt)→ 实际时长 ≈ 35.5 ns
  时间(秒)= duration × dt
→ 所有 OpenPulse 中的时长都以 dt 为单位

常见包络形状:

Gaussian(duration, amp, sigma)
  经典高斯脉冲,适合长脉冲;短脉冲时频谱泄漏严重
GaussianSquare(duration, amp, sigma, width)
  高斯上升/下降 + 方波平台,适合双门与读出
Drag(duration, amp, sigma, beta)
  高斯 + DRAG 校正(beta 项),压制泄漏到 |2⟩
Constant(duration, amp)
  方波,简单但频谱最差

心智:脉冲的本质是「一条复数包络」——振幅给旋转角度(面积决定总角度),相位给旋转轴,时长以 dt 为单位。选择包络形状就是在「时域短」与「频域窄」之间做取舍:时域越短,频域越宽,越容易误驱动邻近能级与比特。


3. OpenPulse 的核心概念

通道(Channel):

DriveChannel(i)   :比特 i 的驱动通道(微波脉冲)
ControlChannel(i) :比特 i 的控制通道(双门调制)
MeasureChannel(i) :比特 i 的读出通道(探测脉冲)
AcquireChannel(i) :比特 i 的采集通道(ADC 采样窗口)

指令(Instruction):

Play(pulse, channel)       :在通道上播放脉冲
Delay(duration, channel)   :等待若干 dt
ShiftPhase / SetPhase      :相对 / 绝对设置通道相位(虚拟 Z 门)
ShiftFrequency / SetFrequency:相对 / 绝对设置通道频率
Acquire(duration, acq_ch, reg_slot, kernel):采集并存入寄存器

Schedule 与 Builder:

Schedule:由 (开始时间, 指令) 组成的脉冲序列
  带通道对齐规则(如 align_left / align_right / align_sequential)
pulse.build():上下文管理器,自动处理通道与对齐
→ 这是构造脉冲序列的推荐方式
from qiskit import pulse
from qiskit.pulse.library import Gaussian, Drag, GaussianSquare

with pulse.build(backend, name="my_gate") as sched:
    d0 = pulse.DriveChannel(0)
    m0 = pulse.MeasureChannel(0)
    a0 = pulse.AcquireChannel(0)
    reg = pulse.MemorySlot(0)

    pulse.play(Gaussian(160, 0.15, 40), d0)   # 驱动脉冲
    pulse.play(GaussianSquare(1600, 0.2, 64, 1200), m0)  # 读出脉冲
    pulse.acquire(1600, a0, reg)              # 采集

心智:OpenPulse 的三要素是「通道 + 指令 + 时序」——通道决定「作用在哪」,指令决定「做什么」,Schedule 决定「什么时候」。pulse.build() 把这些包装成声明式代码,对齐规则帮你处理时序冲突。


4. 用 Qiskit Pulse 实现自定义门

一个自定义旋转门(绕任意轴):

from qiskit import pulse
from qiskit.pulse.library import Gaussian

def rotation_schedule(backend, qubit, angle, axis_phase):
    """绕 axis_phase 指定的轴旋转 angle 弧度"""
    d = pulse.DriveChannel(qubit)
    amp = 0.15 * (angle / (3.14159265 / 2))   # 面积 ∝ angle
    with pulse.build(backend) as sched:
        pulse.shift_phase(axis_phase, d)
        pulse.play(Gaussian(160, amp, 40), d)
        pulse.shift_phase(-axis_phase, d)      # 恢复相位
    return sched

DRAG 拖尾校正:

问题:短的高斯脉冲频谱宽,会把布居泄漏到 |2⟩
DRAG:Q(t) = -λ · (1/α) · dI(t)/dt
  α:比特非简谐度,λ:可调缩放因子
→ 用 I 的导数生成 Q,抵消 |1⟩↔|2⟩ 的跃迁路径
from qiskit.pulse.library import Drag

with pulse.build(backend, name="x_drag") as sched:
    # beta = DRAG 参数,正比于 1/alpha,典型 0.3 ~ 0.5
    pulse.play(Drag(duration=160, amp=0.15, sigma=40, beta=0.35),
               pulse.DriveChannel(0))

虚拟 Z 门(零时长):

Rz(θ) 不需要真实脉冲:
  只需 shift_phase(θ, DriveChannel) 平移后续脉冲的相位
  → 零时长、零误差
→ 这就是编译器能把 Rz 门「免费」处理的原因

心智:脉冲级编程的「杀手级应用」是 DRAG 与虚拟 Z 门——DRAG 用包络导数换更少的泄漏,虚拟 Z 门用相位平移换零时长的 Z 旋转。理解这两者,就理解了「为什么脉冲级能把保真度再往上推」。


5. 测量与采集

读出的脉冲序列:

measure(qubit) 展开为:
  1. 在 MeasureChannel 上播放读出脉冲(GaussianSquare)
  2. 在 AcquireChannel 上开一个采集窗口(Acquire)
  3. 采样得到的信号经「核函数(kernel)」积分 → 单发判读
with pulse.build(backend) as measure_sched:
    pulse.play(
        GaussianSquare(duration=1600, amp=0.2, sigma=64, width=1200),
        pulse.MeasureChannel(0),
    )
    pulse.acquire(1600, pulse.AcquireChannel(0), pulse.MemorySlot(0))

kernel 与鉴别器:

kernel:把 ADC 采样的时域信号加权积分成一个复数(I + iQ)
  常用「最优核」= 区分 |0⟩ 与 |1⟩ 信号点的判别方向
判别器(discriminator):把复数点映射到 0/1
  标定方式:制备 |0⟩ 与 |1⟩,统计两点分布,取分界线
→ 读出保真度由「信号分离度 / 噪声」与 kernel 共同决定

四者的可调参数分别是:MeasureChannel 脉冲的振幅、时长与形状;AcquireChannel 窗口的采集时长与延迟;kernel 的核权重(由标定得出);discriminator 的分界线与阈值。

心智:读出的质量取决于「脉冲 + 采集 + 核 + 判别器」四件套——脉冲决定探测强度,采集窗口决定信噪比,kernel 决定如何把时域信号压成一个点,判别器决定如何切开两类。脉冲级编程让你能逐项调优这四者。


6. 校准实验编排

用 Schedule 编排 Rabi 扫描:

import numpy as np
from qiskit import pulse
from qiskit.pulse.library import Gaussian

def rabi_schedules(backend, qubit, amp=0.15, max_dur=400, step=8):
    d = pulse.DriveChannel(qubit)
    for dur in np.arange(step, max_dur, step):
        with pulse.build(backend) as sched:
            pulse.play(Gaussian(dur, amp, dur / 4), d)
            pulse.measure(qubit)
        yield dur, sched

Ramsey / 回波 / RB 的编排要点:

Ramsey:
  pi/2 -- delay(tau) -- pi/2 -- measure
  关键:两个 pi/2 之间用 pulse.delay 精确控制自由演化时间
回波:
  pi/2 -- delay(tau/2) -- pi -- delay(tau/2) -- pi/2 -- measure
RB:
  用随机 Clifford 序列,每条 Clifford 展开为脉冲序列
  需保证「不同 Clifford 的脉冲时长一致」以避免引入额外误差

校准流水线的自动化:

1. 生成一批 Schedule(扫描参数)
2. 批量提交到后端(backend.run(schedules))
3. 收集计数 → 拟合 → 提取参数(π 时长、失谐、T1/T2)
4. 用新参数更新 backend.defaults() 或构建新的 Schedule
5. 定时/触发式重复
→ 这正是「自动校准流水线」在脉冲层的实现

心智:校准实验的本质是「用 Schedule 编排一次参数扫描」——Rabi 扫描时长、Ramsey 扫描延迟、RB 扫描序列长度,都是同一套「生成 Schedule 批 → 提交 → 拟合」的流程。把这套流程自动化,就是脉冲级的校准流水线。


7. 硬件限制

1. 带宽限制
   AWG 与混频器的可用带宽有限
   脉冲越短 → 频谱越宽 → 越容易超出带宽、误驱动邻近能级
2. 采样率限制
   时长必须是 dt 的整数倍 → 无法实现任意精度的时序
3. 串扰
   DriveChannel 之间的电磁串扰、ControlChannel 的调制泄漏
   → 驱动一个比特时邻居被部分旋转
4. 泄漏到 |2⟩
   短脉冲的高频分量会激发 |1⟩↔|2⟩ 跃迁
   → 靠 DRAG 与更长的脉冲压制
5. 频率拥挤
   比特频率与读出腔频率接近时,驱动会误触读出腔
6. 热噪声与仪器漂移
   AWG 输出漂移、衰减器温度漂移 → 需要周期性重校准

对应的缓解手段是:带宽限制靠加长脉冲与整形包络;采样率限制靠用 dt 的整数倍规划时序;串扰靠频率规划与串扰抵消脉冲;泄漏到 |2⟩ 靠 DRAG 与更长脉冲;仪器漂移靠周期性重校准。

心智:脉冲级编程的每一条「自由度」都被硬件限制反向约束——带宽限制包络的频谱宽度、采样率限制时序精度、串扰限制并行驱动、泄漏限制脉冲时长。好的脉冲设计就是在这组约束下寻找最优解。


8. 与门级编译的关系

门级到脉冲级的编译链:

QuantumCircuit
  ↓ transpile(映射、路由、优化)
Transpiled Circuit
  ↓ 门 → 脉冲展开(schedule 生成)
Schedule
  ↓ assemble(打包成 Qobj / 后端可执行格式)
Backend Job
→ 脉冲级编译的产物就是一个 Schedule

脉冲级优化能做什么:

1. 相位累加:把连续的 Rz 合并成一次 shift_phase
2. 门合并:把相邻的旋转合并成一条脉冲
3. 对齐优化:让并行的门共享时间窗口,缩短总时长
4. 串扰抵消:在空闲通道上插入补偿脉冲
→ 这些优化在门级看不到,必须下探到脉冲级

门级与脉冲级的边界:

门级该做的:算法表达、逻辑优化、映射路由
脉冲级该做的:物理保真度、校准、串扰与泄漏压制
→ 两者的分工是「逻辑正确性」与「物理正确性」
  不要用脉冲级去做门级该做的事(可移植性会崩)

心智:脉冲级编译的目标是「物理保真度」,门级编译的目标是「逻辑正确性」——脉冲级能做的优化(相位累加、门合并、串扰抵消)在门级不可见,但代价是丧失硬件无关性。因此脉冲级代码通常与具体后端强绑定。


9. 平台支持与版本迁移

平台支持现状:

- IBM Quantum:早期通过 OpenPulse 提供脉冲级访问
  但近年逐步收紧,多数公开后端不再开放 pulse 接口
- 自研超导平台:Qiskit Pulse 仍是主流控制框架
- 其他厂商(Rigetti、IQM 等):有各自的脉冲级 SDK
→ 脉冲级编程目前更多是「实验室 / 自研平台」的能力
  而非通用云服务的能力

迁移到 Qiskit 1.x / 2.x 的变化:

1. qiskit.pulse 在 Qiskit 1.0 中被标记为「实验性」,后续逐步弱化,
   官方推荐用 qiskit-experiments 做校准
2. Qiskit 1.x 引入 BackendV2,target 对象承载指令与时长信息,
   旧的 backend.defaults() / backend.configuration() 被替换
3. Qiskit 2.x 进一步精简 pulse 生态,部分厂商转向自研控制栈
→ 迁移要点:用 target 读校准数据、用 qiskit-experiments 做实验,
   把脉冲级代码与具体后端解耦以降低迁移成本

心智:脉冲级编程正在从「通用云服务能力」退回「自研平台能力」——IBM 等厂商逐步收紧公开的 pulse 接口,把校准与脉冲控制收回内部。对多数团队而言,现实的策略是用 qiskit-experiments 做校准、用 target 读数据,只在自研硬件上才深入 OpenPulse。


速查表

主题结论
下探动机更短电路、更高保真、灵活校准
脉冲本质复数包络 × 载波,面积定角度、相位定轴
dt 单位时长以 dt 计,典型 dt ≈ 0.222 ns
四类通道Drive / Control / Measure / Acquire
核心指令Play、Delay、ShiftPhase、SetFrequency、Acquire
Schedule(开始时间, 指令) 序列,带对齐规则
DRAGQ(t) = -λ(1/α)dI/dt,压制泄漏到 |2⟩
虚拟 Z 门shift_phase 实现零时长 Rz
读出四件套脉冲 + 采集 + kernel + 判别器
校准编排生成 Schedule 批 → 提交 → 拟合 → 更新
硬件限制带宽、采样率、串扰、泄漏、漂移
与门级关系脉冲级管物理保真,门级管逻辑正确
平台现状通用云服务收紧,回归自研平台能力
版本迁移pulse 弱化,用 target + qiskit-experiments

一句话记忆:脉冲级编程是「门级之下」的一层抽象,下探的动机只有三个——更短的电路(相位累加、门合并)、更高的保真度(DRAG、包络整形)、更灵活的校准(Rabi/Ramsey/RB 编排);脉冲的本质是一条复数包络,面积决定旋转角、相位决定旋转轴、时长以 dt 为单位;OpenPulse 用「通道 + 指令 + Schedule」描述脉冲序列,用 pulse.build() 声明式构造;DRAG 用包络导数压制泄漏到 |2⟩,虚拟 Z 门用相位平移实现零时长 Rz;读出质量取决于「脉冲 + 采集 + kernel + 判别器」四件套;每条自由度都被带宽、采样率、串扰、泄漏、漂移这些硬件限制反向约束;脉冲级管物理保真度、门级管逻辑正确性,两者分工明确;当前脉冲级接口正从通用云服务收紧为自研平台能力,迁移要点是用 target 读数据、用 qiskit-experiments 做校准。(延伸见 量子比特校准与噪声表征 、Qiskit 编程入门 。)


延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「quantum」更多文章

  1. 开放量子系统与退相干建模:密度矩阵、Kraus 与 Lindblad 方程
  2. 量子基准测试与性能指标:保真度、量子体积与 CLOPS
  3. 量子编译器与电路转译:从逻辑线路到硬件脉冲