feat: math core v3 engine upgrade
This commit is contained in:
@@ -13,11 +13,15 @@ import logging
|
||||
import math
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timezone
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import asyncpg
|
||||
|
||||
from services.shared.schemas import TrendSummary
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from services.aggregation.regime import V3RegimeClassification
|
||||
|
||||
logger = logging.getLogger("projection")
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -493,3 +497,101 @@ async def persist_trend_projection(
|
||||
projection.diverges_from_current,
|
||||
)
|
||||
return str(row_id)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# V3 Posterior State Projection (Requirements: 11.1–11.7)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
# Regime decay factors (phi) — Req 11.3
|
||||
_V3_PHI_DECAY: dict[str, float] = {
|
||||
"panic": 0.35,
|
||||
"trend_following": 0.80,
|
||||
"mean_reversion": 0.55,
|
||||
"uncertainty": 0.50,
|
||||
}
|
||||
|
||||
|
||||
def _logit(p: float) -> float:
|
||||
"""Compute logit = ln(p / (1-p)) with boundary guard."""
|
||||
p = max(1e-10, min(1 - 1e-10, p))
|
||||
return math.log(p / (1 - p))
|
||||
|
||||
|
||||
def _sigmoid(x: float) -> float:
|
||||
"""Compute sigmoid = 1 / (1 + exp(-x)) with overflow guard."""
|
||||
if x > 500:
|
||||
return 1.0
|
||||
if x < -500:
|
||||
return 0.0
|
||||
return 1.0 / (1.0 + math.exp(-x))
|
||||
|
||||
|
||||
@dataclass
|
||||
class V3ProjectionState:
|
||||
"""V3 posterior state projection result.
|
||||
|
||||
Attributes:
|
||||
a_t: Accumulated evidence state A_t.
|
||||
p_up_projected: Projected probability sigmoid(logit(P_prior) + phi^h * A_t).
|
||||
projected_strength: abs(2 * P_up_projected - 1).
|
||||
diverges: True when sign(P_up_projected - 0.5) != sign(P_up_t - 0.5).
|
||||
phi_regime: Regime-specific decay factor used.
|
||||
"""
|
||||
|
||||
a_t: float
|
||||
p_up_projected: float
|
||||
projected_strength: float
|
||||
diverges: bool
|
||||
phi_regime: float
|
||||
|
||||
|
||||
def compute_v3_projection(
|
||||
a_prev: float,
|
||||
cluster_llrs: list[float],
|
||||
regime: V3RegimeClassification,
|
||||
p_prior: float,
|
||||
projection_horizon: int,
|
||||
known_catalyst_llr: float = 0.0,
|
||||
) -> V3ProjectionState:
|
||||
"""Compute posterior state projection with regime-aware decay.
|
||||
|
||||
Evidence state: A_t = phi_regime * A_{t-1} + sum(LLR_c), init A_0 = 0.0
|
||||
Projected alpha: A_projected = phi^h * A_t + known_catalyst_LLR
|
||||
P_up_projected = sigmoid(logit(P_prior) + A_projected)
|
||||
Projected strength = abs(2 * P_up_projected - 1)
|
||||
Divergence flagged when sign(P_up_projected - 0.5) != sign(P_up_t - 0.5)
|
||||
|
||||
Requirements: 11.1–11.7
|
||||
"""
|
||||
# Resolve phi from regime; default to uncertainty (0.50) if unavailable (Req 11.7)
|
||||
phi = _V3_PHI_DECAY.get(regime.regime.value, 0.50) if regime else 0.50
|
||||
|
||||
# Evidence state update: A_t = phi * A_{t-1} + sum(LLR_c) — Req 11.1, 11.2
|
||||
a_t = phi * a_prev + sum(cluster_llrs)
|
||||
|
||||
# Projected alpha: A_projected = phi^h * A_t + known_catalyst_LLR — Req 11.4
|
||||
a_projected = (phi ** projection_horizon) * a_t + known_catalyst_llr
|
||||
|
||||
# P_up_projected = sigmoid(logit(P_prior) + A_projected) — Req 11.5
|
||||
p_up_projected = _sigmoid(_logit(p_prior) + a_projected)
|
||||
|
||||
# Projected strength = abs(2 * P_up_projected - 1) — Req 11.6
|
||||
projected_strength = abs(2.0 * p_up_projected - 1.0)
|
||||
|
||||
# Compute current P_up_t for divergence check (not projected)
|
||||
p_up_t = _sigmoid(_logit(p_prior) + a_t)
|
||||
|
||||
# Flag divergence when projected direction differs from current — Req 11.6
|
||||
sign_projected = (p_up_projected - 0.5) >= 0
|
||||
sign_current = (p_up_t - 0.5) >= 0
|
||||
diverges = sign_projected != sign_current
|
||||
|
||||
return V3ProjectionState(
|
||||
a_t=a_t,
|
||||
p_up_projected=p_up_projected,
|
||||
projected_strength=projected_strength,
|
||||
diverges=diverges,
|
||||
phi_regime=phi,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user