语义层(L4)

qaiji.core.semantics 是 L4 语义授权层:它在同一个 Circuit 之上 回答两个正交问题。分类(枚举、标注和注册表)回答"这个操作对测量统计 做了什么";保持性判决回答"变换后的电路,算符是否仍然(至多 差一个全局相位)等于原来的电路"。两者可以给出不同答案而互不矛盾——例如 RZ(2*pi) 在分类层归为 IDENTITY``(测量统计意义上的恒等),在判决层却判为 ``UP_TO_PHASE``(算符差一个 ``-1 因子);这是两个独立坐标轴,不是同一个问题 答错了。本层不导入 qaiji.codec、OpenQASM 解析依赖或 numpy,由双门控的 导入纯度测试守护。本仓已有 L2 原生调度,但尚不生成硬件 ISA;L4 的 保持性判决不认证 L2 展开、资源或时序,后者由 L2 原生调度接口 的独立校验处理。 可运行的分类、摘要与哈希示例见 L4 语义摘要与保持性。

分类枚举与语义标注

class qaiji.core.semantics.MorphismType(*values)[源代码]

一个操作施加在量子态上的变换种类。

UNITARY = 'UNITARY'
PERMUTATION = 'PERMUTATION'
MEASUREMENT = 'MEASUREMENT'
PHASE = 'PHASE'
IDENTITY = 'IDENTITY'
CLASSICAL_CTRL = 'CLASSICAL_CTRL'
class qaiji.core.semantics.EquivLevel(*values)[源代码]

保持性裁决可以断言的等价强度。

只有 EXACT 与 UP_TO_PHASE 是可判定的;UP_TO_LOCAL 与 ENTANGLEMENT 是为后续层预留的词汇,会在判定入口处被拒绝。

EXACT = 'EXACT'
UP_TO_PHASE = 'UP_TO_PHASE'
UP_TO_LOCAL = 'UP_TO_LOCAL'
ENTANGLEMENT = 'ENTANGLEMENT'
class qaiji.core.semantics.CartanRole(*values)[源代码]

仅供参考的 Cartan 分解角色;绝不作为裁决的输入。

K = 'K'
A = 'A'
MIXED = 'MIXED'
NONE = 'NONE'
class qaiji.core.semantics.ConditionModel(*values)[源代码]

电路的经典条件是如何被求值的。

FPROC_PLACEHOLDER 没有任何生产路径 —— 它只是为多条件前馈预留 位置,而不是声称已经支持。

REGISTER_ALU = 'REGISTER_ALU'
FPROC_PLACEHOLDER = 'FPROC_PLACEHOLDER'
class qaiji.core.semantics.SemanticAnnotation(gate_index, morphism, equiv_level=None, cartan=CartanRole.NONE, body_offset=None, notes=())[源代码]

一个操作的语义含义,以及它在电路中的位置。

坐标遵循 INV-NUM 不变量:顶层节点是 (index, None);Conditional 体内的门是 (父节点 index, offset)。body_offset 为 None 和为 0 是两个不同的 节点,在序列化传输时绝不可混为一谈。

示例

>>> from qaiji.core.semantics.annotation import SemanticAnnotation
>>> from qaiji.core.semantics.types import MorphismType
>>> SemanticAnnotation(gate_index=0, morphism=MorphismType.UNITARY).cartan
<CartanRole.NONE: 'NONE'>
参数:

操作分类

qaiji.core.semantics.classify_operation(op, *, gate_index=-1)[源代码]

将一个操作节点分类为一条或多条标注。

Gate 或 Measure 产出一条标注。Conditional 产出一条节点级的 CLASSICAL_CTRL 裁决,后面跟着体内每个门各一条标注、各自携带该门自身的态射:分支语义归属于 节点本身,因此改写体内标注会导致控制被重复计算,同时丢失分支实际执行的内容。

参数:
  • op (Gate | Measure | Conditional) -- 一个 Gate、Measure 或 Conditional 节点。

  • gate_index (int) -- 该节点在 Circuit.gates 中的位置。默认值 -1 标记这是一次 游离探针;用它产出的结果不得拼接成序列(那种场景请用 annotate_circuit)。

返回:

按位置顺序排列的标注。

抛出:
  • KeyError -- 该门类型不在分类表中。

  • TypeError -- op 不属于三种操作节点类型之一。

返回类型:

tuple[SemanticAnnotation, ...]

qaiji.core.semantics.annotate_circuit(circuit)[源代码]

对整个电路做分类,并为每条标注分配位置。

这是编号的权威入口:下标在这里生成,而不是由调用方事后回填,因此没有任何标注 能带着"游离探针"哨兵值逃逸出去。

参数:

circuit (Circuit) -- 待标注的电路。

返回:

按顶层顺序排列的标注,每个 Conditional 紧跟其体内标注。

抛出:
  • KeyError -- 由无法分类的门类型向上传播。

  • TypeError -- 由非预期的节点类型向上传播。

返回类型:

tuple[SemanticAnnotation, ...]

数据流:测量与条件读取

这里的边只按寄存器名连接测量与条件,即使条件出现在测量之前也会形成边; 它不证明因果顺序。读前写入与结果就绪时间由 L2 调度校验。

class qaiji.core.semantics.MeasurementHandle(measurement_id, qubit_index, creg_name, creg_index, source='measure_node')[源代码]

指向某次测量的经典目的地的句柄。

参数:
  • measurement_id (str)

  • qubit_index (int)

  • creg_name (str)

  • creg_index (int)

  • source (str)

class qaiji.core.semantics.ClassicalEdge(source_handle, target, edge_kind='measurement_to_condition')[源代码]

从一次测量指向一个条件节点的声明式数据流边。

参数:
  • source_handle (str)

  • target (str)

  • edge_kind (str)

qaiji.core.semantics.build_dataflow_summary(circuit)[源代码]

直接读取电路中一等公民的测量节点与条件节点。

只要测量句柄与条件节点共享同一个寄存器名,二者之间就连一条边;寄存器级条件 读取整个寄存器,因此写入该寄存器的每一个句柄都会被连上。这些边表达的是声明式 数据流,而非因果证明:即便某个 Conditional 在门序中排在与之匹配的 Measure 之前,边依然会连上 —— 顺序与因果属于 L2 调度层的议题,不由语义层判定。

参数:

circuit (Circuit) -- 待读取的电路。

返回:

一个 dict,含 measurement_handles,即 MeasurementHandle 元组;以及 classical_edges,即 ClassicalEdge 元组 —— 都是带类型的值对象,尚未 JSON 编码;那一步投影是 summary.py 的职责,正如 operations 的编码也 归它所有。另含 condition_model,取值为 ConditionModel.REGISTER_ALU.value 或 None,始终存在;以及 unitary_segment_count,即顶层 measure 数量 加一。

返回类型:

dict[str, Any]

摘要与规范身份哈希

qaiji.core.semantics.SUMMARY_SCHEMA_VERSION = 'qaiji.semantic_summary.v0'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

qaiji.core.semantics.GATE_COVERAGE_TOTAL = 19

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating-point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer iteral. >>> int('0b100', base=0) 4

qaiji.core.semantics.build_semantic_summary(*, circuit, annotations, status_label='available', source_language=None, preservation=None)[源代码]

构建一个电路的规范化、JSON 安全的语义摘要。

全部 14 个稳定键都无条件输出,包括空容器和 None:一个时有时无的键会让键的 漂移只能表现为哈希差异,而不是显式的键名差异,从而变得不可见。

参数:
  • circuit (Circuit) -- 判别性键(num_qubits、cregs、operations)与 gate_coverage 的来源。

  • annotations (Sequence[SemanticAnnotation]) -- 该电路的语义标注,按 annotate_circuit 的顺序排列。

  • status_label (str) -- 取自 HandleStatus 的值(本函数不做校验,按原样写入的 普通 str)。

  • source_language (str | None) -- 可选的溯源标签。生产调用方保持为 None;只有测试会传入 具体值。

  • preservation (Mapping[str, Any] | None) -- 可选的保持性裁决载荷,给定时原样并入。

返回:

一个 JSON 安全的 dict,含 14 个稳定键,外加所有被赋值的可选键。

返回类型:

dict[str, Any]

qaiji.core.semantics.canonical_summary_hash(summary)[源代码]

将语义摘要哈希为它的规范化内容身份。

参数:

summary (Mapping[str, Any]) -- 一份语义摘要,原始的或已冻结的(freeze_summary 的输出)—— 二者经由 default= 钩子哈希出完全相同的结果。

返回:

规范化 JSON 编码的 "sha256:" + 十六进制摘要。

抛出:
  • ValueError -- 摘要中含有 NaN 或 Infinity。

  • TypeError -- 摘要中含有既非 JSON 原始类型、也非 Mapping 的值。

返回类型:

str

保持性判决与语义句柄

class qaiji.core.semantics.PreservationSummary(stage='unspecified_transform', status='planned', diagnostic_count=0, failed_gate_indices=(), equiv_level=None, original_morphism=None, lowered_morphism=None, pass_trace_ref=None)[源代码]

针对一次受检变换的裁决,沿用上游的 8 字段形状。

示例

>>> from qaiji.core.semantics.preservation import PreservationSummary
>>> from qaiji.core.semantics.types import EquivLevel
>>> PreservationSummary(status="passed", equiv_level=EquivLevel.EXACT).status
'passed'
参数:
qaiji.core.semantics.check_preservation(original, transformed, *, stage='unspecified_transform', requested_level=EquivLevel.UP_TO_PHASE)[源代码]

判定 transformed 是否保持了 original 的算符语义。

流水线是严格的优先级顺序:测量湮灭(第 1 步)压过判定域前置条件(第 2 步), 后者又压过逐位置的 R1-R4 比对(第 3-4 步)。任何落在可判定集合之外的情况一律 判为 unsupported,绝不给出一个静默错误的 passed,见 I-Q4.6。

参数:
  • original (Circuit) -- 变换前的电路。

  • transformed (Circuit) -- 变换后的电路。

  • stage (str) -- 本次裁决针对的是哪一个受检变换。

  • requested_level (EquivLevel) -- 调用方能接受的等价上限。EXACT 要求全局相位已抵消; UP_TO_PHASE 为默认值,两者皆可接受。

返回:

一个 PreservationSummary,在包括 failed/unsupported 在内的每条 分支上都填好了诊断用的态射字段。

抛出:
  • UnsupportedEquivLevelError -- requested_level 为 UP_TO_LOCAL 或 ENTANGLEMENT —— 本流水线无法判定。

  • ValueError -- stage 不属于已知的 stage 字面量(由本次调用构造的第一个 裁决在 PreservationSummary.__post_init__ 中抛出)。

返回类型:

PreservationSummary

class qaiji.core.semantics.SemanticIRHandle(schema_version='qaiji.semantic_ir_handle.v0', handle_id=None, producer=None, summary=<factory>, content_hash=None, status=HandleStatus.PLANNED)[源代码]

下游坍缩阶段消费的唯一对象:摘要、哈希与状态。

示例

>>> from qaiji.core.semantics.handle import SemanticIRHandle
>>> SemanticIRHandle().status
<HandleStatus.PLANNED: 'planned'>
参数:
class qaiji.core.semantics.HandleStatus(*values)[源代码]

句柄摘要载荷的可用性状态。

只有四个取值,而非上游的五个:qaiji 不存在"不适用"的句柄场景,因此 NOT_APPLICABLE 是被有意舍弃的。

AVAILABLE = 'available'
PLANNED = 'planned'
OMITTED = 'omitted'
FAILED = 'failed'
qaiji.core.semantics.freeze_summary(value)[源代码]

递归冻结一个 JSON 形状的映射,得到不可变树。

每个 Mapping 变成 MappingProxyType;每个 list/tuple 变成 tuple。与本实现所借鉴的上游模型不同(上游把嵌套容器重建为新的、仍然可变的 list),这里的冻结是深度不可变的:真正做到这一点的是 tuple 转换,而不是某种 共享引用的取巧手法。

参数:

value (Mapping[str, Any]) -- JSON 形状的映射,原始的或已冻结的均可(幂等)。

返回:

每一层都已冻结的同一棵树。

抛出:

TypeError -- 映射的键不是 str,或叶子值不属于 None/bool/int/float/str/list/tuple/Mapping。

返回类型:

Mapping[str, JSONValue]

qaiji.core.semantics.JSONValue

Type alias.

Type aliases are created through the type statement:

type Alias = int

In this example, Alias and int will be treated equivalently by static type checkers.

At runtime, Alias is an instance of TypeAliasType. The __name__ attribute holds the name of the type alias. The value of the type alias is stored in the __value__ attribute. It is evaluated lazily, so the value is computed only if the attribute is accessed.

Type aliases can also be generic:

type ListOrSet[T] = list[T] | set[T]

In this case, the type parameters of the alias are stored in the __type_params__ attribute.

See PEP 695 for more information.