快速开始
概述
本章将引导你在 5 分钟内完成 UnitaryLab 模拟器的上手流程。完成后,你将能够:
- 使用
Circuit创建量子线路 - 添加基本量子门
- 执行模拟并读取状态向量和概率分布
- 添加测量并读取经典比特结果
推荐导入方式
from unitarylab import Circuit, Register, ClassicalRegisterCircuit、Register、ClassicalRegister 是 unitarylab 包顶层直接导出的三个名称(等价写法:from unitarylab.core import Circuit, Register, ClassicalRegister),也是用户最常用的高层接口,绝大多数操作都通过它们完成。底层的 GateSequence、CircuitExecutor 等在普通使用中无需直接导入。
最小示例:Bell 态
Bell 态是量子纠缠的标准示例,由一个 Hadamard 门和一个 CNOT 门构成。
from unitarylab import Circuit
# 1. 创建 2 量子比特线路
qc = Circuit(2)
# 2. 对第 0 号量子比特施加 Hadamard 门
qc.h(0)
# 3. 添加 CNOT 门(控制比特 0,目标比特 1)
qc.cx(0, 1)
# 4. 执行模拟
result = qc.execute()
# 5. 查看状态向量
print(result.state)预期输出:
[0.70710678+0.j 0. +0.j 0. +0.j 0.70710678+0.j]查看概率分布
probs = result.probabilities
print(probs)预期输出:
{'00': 0.4999999999999999, '11': 0.4999999999999999}probabilities 返回一个字典,键为计算基态的二进制字符串(little-endian,最低位对应 qubit 0),值为对应的测量概率。Bell 态下 |00⟩ 和 |11⟩ 各占约 50%。
添加测量
Circuit(n) 这种整数构造方式会自动创建默认量子寄存器 Register('q', n) 和默认经典寄存器 ClassicalRegister('c', n),因此不需要显式创建经典寄存器也可以直接调用 measure():
from unitarylab import Circuit
qc = Circuit(2) # 已自动创建名为 'q' 的 2 量子比特寄存器和名为 'c' 的 2 经典比特寄存器
qc.h(0)
qc.cx(0, 1)
# 将量子比特 0、1 的测量结果存入经典比特 0、1
qc.measure([0, 1], [0, 1])
result = qc.execute()
print(result.classical_results_map)只有在需要自定义寄存器命名、使用多个寄存器或自定义量子/经典比特布局时,才需要显式构造 Register/ClassicalRegister 并传入 Circuit:
from unitarylab import Circuit, Register, ClassicalRegister
qr = Register('q', 2)
cr = ClassicalRegister('c', 2)
qc = Circuit(qr, cr)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
result = qc.execute()
print(result.classical_results_map)预期输出(默认 seed=42,结果确定不变):
{0: 1, 1: 1}classical_results_map 是经典比特索引到测量值(0 或 1)的映射。Bell 态的测量结果总是两比特相同(00 或 11),体现了量子纠缠。若改用 qc.execute(seed=None) 或其他种子,每次运行的结果会在 {0: 0, 1: 0} 与 {0: 1, 1: 1} 之间随机变化。
执行参数:shots、seed、backend_options
execute() 的完整参数为:
result = qc.execute(
initial_state=None, # 初始态,默认从 |0...0⟩ 开始
backend='torch', # 'torch'(默认)/ 'numpy' / 'cpp' / 'tensornet'
device='cpu', # 'cpu' 或 'gpu'(仅 backend='torch' 支持 gpu)
dtype=np.complex128, # 复数精度,默认 complex128;会按后端自动归一化(如整数/浮点类型会被提升为对应复数类型)
shots=1, # 独立重复执行次数
seed=42, # 测量随机种子;None 表示不固定种子
backend_options=None, # 后端专属选项(tensornet 后端可传 max_bond/cutoff/routing)
)shots大于 1 时,result.state/result.classical_results_map是最后一次执行的结果,而result.counts会汇总所有 shots 的经典比特串统计(键为字符串,值为出现次数)。seed独立控制线路内测量的随机性,默认固定为42,因此不显式传参时结果可复现;需要真正随机的采样时传seed=None。backend_options目前只在backend='tensornet'时生效,用于控制 MPS 的最大键维max_bond、截断阈值cutoff及双比特门路由策略routing('auto'/'swap'/'mpo')。
# 多次采样并统计经典比特串出现次数
qc = Circuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
result = qc.execute(shots=1000, seed=None)
print(result.counts)
# {'00': 498, '11': 502} # 具体数值每次运行不同选择执行后端
execute() 支持 backend 和 device 参数,适用于不同计算环境:
# 使用 PyTorch 后端(默认),在 CPU 上运行
result = qc.execute(backend='torch', device='cpu')
# 使用 NumPy 后端
result = qc.execute(backend='numpy', device='cpu')
# 使用 C++ 编译后端(需要编译扩展可用)
result = qc.execute(backend='cpp', device='cpu')
# 使用张量网络(MPS)后端,适合大比特数、低纠缠线路
result = qc.execute(backend='tensornet', device='cpu')
# 若有 CUDA 或 Apple MPS,可切换到 GPU(仅 torch 后端支持)
import torch
gpu_available = torch.cuda.is_available() or torch.backends.mps.is_available()
if gpu_available:
# Apple MPS 不支持 complex128,因此统一显式使用 complex64
result = qc.execute(backend='torch', device='gpu', dtype=np.complex64)
else:
print('当前环境没有可用 GPU,跳过 GPU 示例。')一般直接调用 qc.execute() 无需指定参数(默认 torch + cpu);比特数很大但线路纠缠有限时可尝试 tensornet 后端;有 GPU 时可用 device='gpu' 加速。
绘制线路图
qc.draw()draw() 会弹出 Matplotlib 线路图。如需保存为文件:
qc.draw(filename='bell.png', title='Bell State')