4eefbfdd74
从 TRM4 core/harness/eprocess.py 逐行迁移,零逻辑变更: - compute_e_value: 截断 Beta 混合 e 值(log 空间 + betainc 对称性) - gate_decision: 四出口优先级链(confirmed→directional→futility→exhaustion→continue) - probation_verdict: 试用期非对称双向结算 - 常量保真: _WALD_WIN=ln1.4, _WALD_LOSS=ln0.6, _SHRINK_PSEUDO=4 仅变更: import 路径 + GateParams/GateVerdict 移至 types.py + 中文 docstring 14 tests 覆盖: e 值数学、边界校验、四出口路径、试用期三分支 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
97 lines
3.2 KiB
Python
97 lines
3.2 KiB
Python
"""CE-Gate e-process 纯函数单元测试。
|
|
|
|
覆盖 compute_e_value、gate_decision、probation_verdict 三个公共函数
|
|
的核心路径与边界条件。
|
|
"""
|
|
|
|
import math
|
|
|
|
import pytest
|
|
|
|
from core.evolution.gate import compute_e_value, gate_decision, probation_verdict
|
|
from core.evolution.types import GateParams, GateVerdict
|
|
|
|
_PARAMS = GateParams(
|
|
e_confirm=20.0,
|
|
e_provisional=3.0,
|
|
w_net_min=2,
|
|
delta_min=0.02,
|
|
lambda_dir=-0.642,
|
|
e_rollback=10.0,
|
|
)
|
|
|
|
|
|
class TestComputeEValue:
|
|
"""compute_e_value 的数学正确性与边界校验。"""
|
|
|
|
def test_zero_zero_returns_one(self) -> None:
|
|
"""W=L=0 时 e 值应为 1(无证据,中性)。"""
|
|
assert compute_e_value(0, 0) == pytest.approx(1.0)
|
|
|
|
def test_negative_w_raises(self) -> None:
|
|
"""负 W 应立即报错。"""
|
|
with pytest.raises(ValueError):
|
|
compute_e_value(-1, 0)
|
|
|
|
def test_negative_l_raises(self) -> None:
|
|
"""负 L 应立即报错。"""
|
|
with pytest.raises(ValueError):
|
|
compute_e_value(0, -1)
|
|
|
|
def test_heavy_loss_returns_near_zero(self) -> None:
|
|
"""重度失败时 e 值趋近于零。"""
|
|
assert compute_e_value(0, 20) < 0.05
|
|
|
|
def test_heavy_win_returns_large(self) -> None:
|
|
"""重度胜利时 e 值远大于 100。"""
|
|
assert compute_e_value(10, 0) > 100
|
|
|
|
def test_symmetric(self) -> None:
|
|
"""W>L 时 e 值应大于 W<L 时。"""
|
|
assert compute_e_value(5, 3) > compute_e_value(3, 5)
|
|
|
|
|
|
class TestGateDecision:
|
|
"""gate_decision 四出口优先级链测试。"""
|
|
|
|
def test_confirmed_needs_both_e_and_delta(self) -> None:
|
|
"""高 e 值 + 足够 delta → accept_confirmed。"""
|
|
v = gate_decision(10, 0, 10, 10, params=_PARAMS)
|
|
assert v.decision == "accept_confirmed"
|
|
|
|
def test_continue_on_balanced(self) -> None:
|
|
"""平衡局面且题未尽 → continue。"""
|
|
v = gate_decision(3, 3, 6, 20, params=_PARAMS)
|
|
assert v.decision == "continue"
|
|
|
|
def test_reject_inertia_on_exhaustion(self) -> None:
|
|
"""题尽且证据不足 → reject_inertia。"""
|
|
v = gate_decision(1, 1, 2, 0, params=_PARAMS)
|
|
assert v.decision == "reject_inertia"
|
|
|
|
def test_n_used_zero_raises(self) -> None:
|
|
"""n_used=0 应立即报错。"""
|
|
with pytest.raises(ValueError):
|
|
gate_decision(0, 0, 0, 10, params=_PARAMS)
|
|
|
|
def test_n_remaining_negative_raises(self) -> None:
|
|
"""n_remaining<0 应立即报错。"""
|
|
with pytest.raises(ValueError):
|
|
gate_decision(1, 0, 1, -1, params=_PARAMS)
|
|
|
|
|
|
class TestProbationVerdict:
|
|
"""probation_verdict 试用期结算测试。"""
|
|
|
|
def test_strong_win_confirmed(self) -> None:
|
|
"""强烈胜利 → confirmed 转正。"""
|
|
assert probation_verdict(10, 0, params=_PARAMS) == "confirmed"
|
|
|
|
def test_strong_loss_rollback(self) -> None:
|
|
"""强烈失败 → rollback 回滚。"""
|
|
assert probation_verdict(0, 10, params=_PARAMS) == "rollback"
|
|
|
|
def test_balanced_unverified(self) -> None:
|
|
"""平衡局面 → unverified 惯性转正。"""
|
|
assert probation_verdict(3, 3, params=_PARAMS) == "unverified"
|