精度与能力 -- 精度选择、模拟器注册表、SIMD 诊断
pyqpanda3.core 的每个 CPU 系列模拟器都在构造时接受算术 precision("float32" 或 "float64"),报告其支持的精度,并在有意义的地方以原生 dtype 返回状态。两个新的查询面与这些旋钮互补:simulator_capabilities() 注册表无需构造任何对象即可回答"这里能运行什么";pyqpanda3.core.simd 子模块暴露运行时 SIMD 分派决定。本页所有接口均为 pyqpanda3 0.5.0 新增。
导入
from pyqpanda3.core import (
CPUQVM,
DensityMatrixSimulator,
InvalidPrecisionError,
MPSQVM,
PrecisionConversionError,
UnsupportedPrecisionError,
simulator_capabilities,
)
from pyqpanda3.core import simd精度选择
构造关键字
precision 是 CPUQVM、DensityMatrixSimulator、MPSQVM、PartialAmplitudeQVM、SingleAmplitudeQVM、SparseHeisenbergSimulator 与 GPUQVM 的构造关键字。它在每个实例上不可变,各处默认为 "float64"。
import numpy as np
from pyqpanda3.core import CPUQVM
seed = np.array([0.5, 0.5, 0.5, 0.5], dtype=np.complex64)
qvm32 = CPUQVM(precision="float32")
qvm32.init_state(seed)
print(qvm32.current_state().dtype, qvm32.current_state().shape, qvm32.precision,
tuple(qvm32.supported_precisions))
qvm64 = CPUQVM()
qvm64.init_state(seed)
print(qvm64.current_state().dtype, qvm64.current_state().shape, qvm64.precision)运行结果:
complex64 (4,) float32 ('float32', 'float64')
complex128 (4,) float64| 属性 | 类型 | 说明 |
|---|---|---|
precision | str | 该实例构造时的算术精度。只读。 |
supported_precisions | tuple[str, ...] | 该模拟器类支持的精度。只读。 |
Stabilizer 报告 precision == "exact" 且 supported_precisions == ("exact",);它以 UnsupportedPrecisionError 拒绝算术精度。
CPUQVM.current_state / MPSQVM.current_state
CPUQVM.current_state() -> numpy.ndarray
MPSQVM.current_state() -> numpy.ndarray以模拟器原生精度的 NumPy 数组返回状态("float32" 对应 complex64,"float64" 对应 complex128)。与 result().get_state_vector() 不同,不发生任何 dtype 转换。
两者返回的状态不同,这一区别至关重要:
| 模拟器 | current_state() 返回什么 |
|---|---|
CPUQVM | 最近一次 init_state(...) 装入的状态。run() 不会填充它——在任何 init_state(...) 调用之前,它是 dtype 正确但内容为空的数组。要读取 run() 产生的状态,请用 result().get_state_vector()。 |
MPSQVM | 最近一次 run() 产生的实时状态。 |
import numpy as np
from pyqpanda3.core import CPUQVM, MPSQVM, CNOT, H, QProg, measure
# CPUQVM:current_state() 镜像 init_state(),run() 不会改变它。
cpu = CPUQVM(precision="float32")
cpu.run(QProg() << H(0) << CNOT(0, 1) << measure([0, 1], [0, 1]), 100)
print("before init_state:", len(cpu.current_state()))
cpu.init_state(np.array([0.5, 0.5, 0.5, 0.5], dtype=np.complex64))
print("after init_state:", cpu.current_state().dtype, cpu.current_state().shape)
print("after run (result path):", len(cpu.result().get_state_vector()))
# MPSQVM:current_state() 就是 run() 之后的状态。
mps = MPSQVM(precision="float32")
mps.run(QProg() << H(0) << CNOT(0, 1), 2)
print("mps:", mps.current_state().dtype, mps.current_state().shape)运行结果:
before init_state: 0
after init_state: complex64 (4,)
after run (result path): 4
mps: complex64 (4,)DensityMatrixSimulator.density_matrix_native
DensityMatrixSimulator.density_matrix_native() -> numpy.ndarray以模拟器原生 dtype 的 NumPy 数组返回密度矩阵。需要恒为 complex128 的视图时使用 density_matrix();需要原生 dtype 向下游流动时使用本方法。
MPS 截断选项与运行统计
MPSQVM(precision: str = "float64", truncation_atol: float | None = None, max_bond_dimension: int | None = None)| 参数 | 类型 | 说明 |
|---|---|---|
| precision | str | "float32" 或 "float64"。默认 "float64"。 |
| truncation_atol | float 或 None | 每次 SVD 后低于该权重的奇异值被丢弃。默认依精度而定:float32 为 1e-6,float64 为 1e-12。 |
| max_bond_dimension | int 或 None | 截断后保留键维的硬上限。None 表示仅按容差驱动截断。 |
MPSQVM.stats() -> MPSRunStatsMPSRunStats 是只读记录,含 discarded_weight(截断至今丢弃的总概率权重)与 max_bond_dimension_seen(至今物化过的最大键维)。
import numpy as np
from pyqpanda3.core import MPSQVM, QProg, RY, CZ
rng = np.random.default_rng(7)
prog = QProg()
for q in range(6):
prog << RY(q, rng.uniform(0, np.pi))
for layer in range(4):
pairs = [(0, 1), (2, 3), (4, 5)] if layer % 2 == 0 else [(1, 2), (3, 4)]
for a, b in pairs:
prog << CZ(a, b) << RY(a, rng.uniform(0, np.pi)) << RY(b, rng.uniform(0, np.pi))
capped = MPSQVM(precision="float64", max_bond_dimension=2)
capped.run(prog, 1)
print(capped.stats().discarded_weight, capped.stats().max_bond_dimension_seen)
exact = MPSQVM()
exact.run(prog, 1)
print(exact.stats().discarded_weight, exact.stats().max_bond_dimension_seen)运行结果:
0.024353811677256556 2
1.8613363972962274e-34 4SingleAmplitudeQVM.stats
SingleAmplitudeQVM.stats() -> SingleAmplitudeStatsSingleAmplitudeStats 是只读记录,含 cache_hit_count、cache_miss_count 与 peak_workspace_bytes,描述最近一次运行的振幅求值工作区行为。
精度异常
非法精度请求会以专属异常类型尽早抛出,均为 ValueError 的子类:
| 异常 | 抛出时机 |
|---|---|
InvalidPrecisionError | 精度字符串不是任何后端可识别的精度名。 |
UnsupportedPrecisionError | 精度名合法但该后端不支持。 |
PrecisionConversionError | 用户请求的精度转换无法执行。 |
from pyqpanda3.core import CPUQVM, Stabilizer
try:
CPUQVM(precision="float16")
except ValueError as e:
print(type(e).__name__, "-", e)
try:
Stabilizer(precision="float32")
except ValueError as e:
print(type(e).__name__, "-", e)运行结果:
InvalidPrecisionError - unknown precision 'float16'
UnsupportedPrecisionError - backend 'Stabilizer' does not support precision 'float32'; supported precisions are: exactBackendUnavailableError(RuntimeError 子类)在构造未注册或构建缺失的模拟器时抛出。注意:无 CUDA 构建中 GPUQVM 不会被注册,pyqpanda3.core.GPUQVM 为 None(导入时发出 ImportWarning),无法构造;能力注册表(下文)以 available=False 报告同一情况。用 simulator_capabilities("GPUQVM").available 判断。
模拟器能力注册表
simulator_capabilities(name: str | None = None) -> SimulatorCapabilities | list[SimulatorCapabilities]| 参数 | 类型 | 说明 |
|---|---|---|
| name | str 或 None | 模拟器类名(例如 "MPSQVM")。省略时返回全部已注册模拟器的记录。 |
SimulatorCapabilities 是只读记录:
| 字段 | 类型 | 说明 |
|---|---|---|
name | str | 模拟器类名。 |
supported_precisions | tuple[str, ...] | 该类支持的精度。 |
default_precision | str | 未指定 precision 时使用的精度。 |
available | bool | 该模拟器在当前主机上能否构造(构建存在、硬件存在)。 |
simd_domain | str | 模拟器所处的计算域:StateVector、Density、Tensor、Amplitude、Sparse 或 NotApplicable。 |
from pyqpanda3.core import simulator_capabilities
for cap in simulator_capabilities():
print(f"{cap.name:26s} {','.join(cap.supported_precisions):16s}"
f" default={cap.default_precision:8s} available={str(cap.available):5s}"
f" domain={cap.simd_domain}")运行结果:
CPUQVM float32,float64 default=float64 available=True domain=StateVector
DensityMatrixSimulator float32,float64 default=float64 available=True domain=Density
GPUQVM float64 default=float64 available=False domain=NotApplicable
MPSQVM float32,float64 default=float64 available=True domain=Tensor
PartialAmplitudeQVM float32,float64 default=float64 available=True domain=Amplitude
SingleAmplitudeQVM float32,float64 default=float64 available=True domain=Amplitude
SparseHeisenbergSimulator float32,float64 default=float64 available=True domain=Sparse
Stabilizer exact default=exact available=True domain=NotApplicableSIMD 诊断与偏好
pyqpanda3.core.simd 子模块报告运行时 SIMD 分派,并允许覆盖它。
simd.capabilities
simd.capabilities() -> SIMDCapabilitiesSIMDCapabilities 是不可变快照,包含:
| 字段 | 类型 | 说明 |
|---|---|---|
architecture | str | 主机架构,例如 x86_64。 |
compiled_backends | list[str] | 编译进本构建的后端:x86_64 为 scalar、sse2、avx2、avx512;ARM64 为 scalar、neon、sve、sve2。 |
available_backends | list[str] | 主机 CPU 实际可执行的已编译后端。 |
default_backend | str | 探测器自动选择的后端。 |
active_backend | str | 当前生效的后端(默认或用户偏好)。 |
fallback_reason | str | 请求的后端未被采纳的原因;无则为空。 |
simd.active_backend
simd.active_backend() -> str返回当前生效的后端。
simd.set_preference
simd.set_preference(backend: str, strict: bool = False) -> None| 参数 | 类型 | 说明 |
|---|---|---|
| backend | str | "auto"、"scalar"、"sse2"、"avx2"、"avx512"、"neon"、"sve"、"sve2" 之一(以编译/可用为准)。 |
| strict | bool | 为 True 时,对不可用后端抛出 UnsupportedSIMDBackendError(RuntimeError 子类)而非记录回退。默认 False。 |
from pyqpanda3.core import simd
cap = simd.capabilities()
print(cap.architecture, list(cap.available_backends), cap.active_backend)
simd.set_preference("scalar")
print(simd.active_backend())
simd.set_preference("auto")
print(simd.active_backend())运行结果(在支持 AVX2 的 x86_64 主机上):
x86_64 ['scalar', 'sse2', 'avx2', 'avx512'] avx2
scalar
avx2该偏好作用于调用之后构造的模拟器。自动提升策略刻意保守:只有当某后端的正确性行全部通过且在发布基准套件上实测运行时间优于下一个安全后端时,它才会成为自动选择(该套件上 AVX2 相对标量的中位加速为 2.13x)。
另见
- 模拟器 -- 各模拟器参考
- 量子门 -- 门家族
- 噪声 --
NoiseModel与误差信道 - v0.5.0 发布说明 -- 引入这些接口的版本