"""core/evolution/validate.py — 块验证纯决策函数。 算法 #7(块顺序验证)的局部实现:pair_block 逐题比对基线与候选、 classify_quadrants 四象限分类、compute_accuracy 纯算术准确率。 三个函数均为纯函数,无副作用、无外部依赖。 """ from core.evolution.types import PairResult, QuadrantClassification def pair_block( baseline: dict[str, bool], candidate: dict[str, bool], question_ids: list[str], ) -> PairResult: """逐题比对基线与候选对错,统计翻转。 参数: baseline: 基线臂每题正确性映射。 candidate: 候选臂每题正确性映射。 question_ids: 参与比对的题目 ID 列表。 返回: PairResult,包含 w(基线错→候选对翻转数)、l(基线对→候选错翻转数) 和 observed(每题的 (基线, 候选) 对错记录)。 """ w = l = 0 # noqa: E741 — 数学记号 W/L(win/loss),与 gate.py 一致 observed: dict[str, tuple[bool, bool]] = {} for qid in question_ids: b, c = baseline[qid], candidate[qid] observed[qid] = (b, c) if not b and c: w += 1 elif b and not c: l += 1 # noqa: E741 return PairResult(w=w, l=l, observed=observed) def classify_quadrants( observed: dict[str, tuple[bool, bool]], ) -> QuadrantClassification: """按 (baseline, candidate) 四组分类,各组内 sorted。 参数: observed: 每题的 (基线是否正确, 候选是否正确) 记录。 返回: QuadrantClassification,四个象限各含排序后的题目 ID 列表。 """ improvements: list[str] = [] regressions: list[str] = [] persistent_fails: list[str] = [] stable_successes: list[str] = [] for qid, (prev, curr) in observed.items(): if not prev and curr: improvements.append(qid) elif prev and not curr: regressions.append(qid) elif not prev and not curr: persistent_fails.append(qid) else: stable_successes.append(qid) return QuadrantClassification( improvements=sorted(improvements), regressions=sorted(regressions), persistent_fails=sorted(persistent_fails), stable_successes=sorted(stable_successes), ) def compute_accuracy( correctness: dict[str, bool], question_ids: list[str], ) -> float: """纯算术:sum(correct) / len(ids)。 参数: correctness: 每题正确性映射。 question_ids: 参与计算的题目 ID 列表。 返回: 准确率浮点数。question_ids 为空时抛出 ZeroDivisionError。 """ return sum(correctness[qid] for qid in question_ids) / len(question_ids)