qaiji.core.native.validation 源代码

# Copyright 2026 Qaiji-IR core developer: Ye Jun <yjmaxpayne@hotmail.com>
# SPDX-License-Identifier: Apache-2.0
"""Independent staged authentication of native schedules."""

from __future__ import annotations

from qaiji.core.circuit import Circuit, Gate
from qaiji.core.classical import Conditional, Measure

from .config import ScheduleConfig
from .diagnostics import CheckResult, GroupEvidence, NativeIssue, NativeValidationReport
from .matrix import _check_local_matrix
from .model import NativeScheduleIR, RegisterDecl, SourceLocation, _copy
from .recognition import _recognize_group
from .source import _capture_source, _SourceSnapshot
from .timing import _check_source_layout, _check_timing


[文档] def validate_native_schedule( circuit: Circuit, schedule: NativeScheduleIR, config: ScheduleConfig ) -> NativeValidationReport: """重建输入值,分别报告来源、规则、算符矩阵与时序的检查结果。""" snapshot = _capture_source(circuit) candidate = _copy(schedule, NativeScheduleIR, "$") configuration = _copy(config, ScheduleConfig, "$") return _validate_snapshot(snapshot, candidate, configuration)
def _result( code: str | None = None, path: str | None = "$", source: SourceLocation | None = None, operation_index: int | None = None, ) -> CheckResult: if code is None: return CheckResult(status="pass", issues=()) issue = NativeIssue( code=code, path=path or "$", source=source, operation_index=operation_index, message=f"Native validation failed: {code}.", ) return CheckResult(status="fail", issues=(issue,)) def _aggregate(checks: tuple[CheckResult, ...]) -> CheckResult: issues = tuple(issue for check in checks for issue in check.issues) if issues: return CheckResult(status="fail", issues=issues) if any(check.status == "not_run" for check in checks): return CheckResult(status="not_run", issues=()) status = "pass" if any(check.status == "pass" for check in checks) else "not_applicable" return CheckResult(status=status, issues=()) def _source_check(snapshot: _SourceSnapshot, schedule: NativeScheduleIR) -> CheckResult: if snapshot.source_kernel_ref != schedule.source_kernel_ref: return _result("source_ref", "$.source_kernel_ref") if snapshot.num_qubits != schedule.num_qubits: return _result("source_header", "$.num_qubits") registers = tuple(RegisterDecl(name=r.name, size=r.size) for r in snapshot.cregs) if registers != schedule.registers: return _result("source_header", "$.registers") layout = _check_source_layout(snapshot, schedule) return _result(layout.code, layout.path, layout.source, layout.operation_index) def _group_evidence( snapshot: _SourceSnapshot, schedule: NativeScheduleIR ) -> tuple[GroupEvidence, ...]: evidence = [] for index, group in enumerate(schedule.groups): node = snapshot.gates[group.source.gate_index] if isinstance(node, Conditional): assert group.source.body_offset is not None node = node.body[group.source.body_offset] assert isinstance(node, (Gate, Measure)) operations = schedule.operations[group.op_start : group.op_stop] rule = _recognize_group(node, group.source, group, operations) path = f"$.groups[{index}]" if rule.code == "rule_id": path += ".rule_id" elif rule.code == "rule_phase": path += ".phase_rad" elif rule.operation_index is not None: path = f"$.operations[{rule.operation_index}]" hp = _check_local_matrix(node, operations) hp_result = ( _result(hp.code, f"$.groups[{index}]", group.source) if hp.code is not None else CheckResult(status=hp.status, issues=()) ) evidence.append( GroupEvidence( source=group.source, rule_id=group.rule_id, rule=_result(rule.code, path, group.source, rule.operation_index), hp=hp_result, expected_phase_rad=hp.expected_phase_rad, max_abs_residual=hp.max_abs_residual, ) ) return tuple(evidence) def _validate_snapshot( snapshot: _SourceSnapshot, schedule: NativeScheduleIR, config: ScheduleConfig ) -> NativeValidationReport: """Consume the same captured source used by generation or projection.""" source = _source_check(snapshot, schedule) if source.status == "fail": pending = CheckResult(status="not_run", issues=()) return NativeValidationReport( source=source, rules=pending, hp=pending, schedule=pending, groups=(), all_results_ready_ns=None, ) groups = _group_evidence(snapshot, schedule) rules = _aggregate(tuple(group.rule for group in groups)) hp = _aggregate(tuple(group.hp for group in groups)) timing = _check_timing(snapshot, schedule, config) schedule_result = _result(timing.code, timing.path, timing.source, timing.operation_index) ready = timing.all_results_ready_ns if rules.status not in ("pass", "not_applicable") or hp.status not in ( "pass", "not_applicable", ): ready = None return NativeValidationReport( source=source, rules=rules, hp=hp, schedule=schedule_result, groups=groups, all_results_ready_ns=ready, )