qaiji.core.semantics.dataflow 源代码

# Copyright 2026 Qaiji-IR core developer: Ye Jun <yjmaxpayne@hotmail.com>
# SPDX-License-Identifier: Apache-2.0
"""电路中一等公民的测量节点与条件节点之间的数据流边。"""

from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING, Any

from qaiji.core.classical import Conditional, Measure
from qaiji.core.semantics.types import ConditionModel

if TYPE_CHECKING:
    from qaiji.core.circuit import Circuit

__all__ = ["ClassicalEdge", "MeasurementHandle", "build_dataflow_summary"]


[文档] @dataclass(frozen=True, slots=True) class MeasurementHandle: """指向某次测量的经典目的地的句柄。""" measurement_id: str qubit_index: int creg_name: str creg_index: int source: str = "measure_node"
[文档] @dataclass(frozen=True, slots=True) class ClassicalEdge: """从一次测量指向一个条件节点的声明式数据流边。""" source_handle: str target: str edge_kind: str = "measurement_to_condition"
[文档] def build_dataflow_summary(circuit: Circuit) -> dict[str, Any]: """直接读取电路中一等公民的测量节点与条件节点。 只要测量句柄与条件节点共享同一个寄存器名,二者之间就连一条边;寄存器级条件 读取整个寄存器,因此写入该寄存器的每一个句柄都会被连上。这些边表达的是声明式 数据流,而非因果证明:即便某个 Conditional 在门序中排在与之匹配的 Measure 之前,边依然会连上 —— 顺序与因果属于 L2 调度层的议题,不由语义层判定。 Args: circuit: 待读取的电路。 Returns: 一个 dict,含 ``measurement_handles``,即 ``MeasurementHandle`` 元组;以及 ``classical_edges``,即 ``ClassicalEdge`` 元组 —— 都是带类型的值对象,尚未 JSON 编码;那一步投影是 summary.py 的职责,正如 ``operations`` 的编码也 归它所有。另含 ``condition_model``,取值为 ``ConditionModel.REGISTER_ALU.value`` 或 ``None``,始终存在;以及 ``unitary_segment_count``,即顶层 measure 数量 加一。 """ handles: list[MeasurementHandle] = [] for operation in circuit.gates: if isinstance(operation, Measure): handles.append( MeasurementHandle( measurement_id=f"m{len(handles)}", qubit_index=operation.qubit, creg_name=operation.target.register.name, creg_index=operation.target.index, ) ) edges: list[ClassicalEdge] = [] has_conditional = False for index, operation in enumerate(circuit.gates): if isinstance(operation, Conditional): has_conditional = True target = f"cond{index}" edges.extend( ClassicalEdge(source_handle=handle.measurement_id, target=target) for handle in handles if handle.creg_name == operation.register.name ) return { "measurement_handles": tuple(handles), "classical_edges": tuple(edges), "condition_model": ConditionModel.REGISTER_ALU.value if has_conditional else None, "unitary_segment_count": len(handles) + 1, }