74 lines
2.6 KiB
Python
74 lines
2.6 KiB
Python
"""core.physics.attention — Attention as controlled field traversal.
|
||
|
||
ADR-0008: Attention is the act of directing cognitive traversal
|
||
along high-salience curvature gradients. The AttentionOperator
|
||
produces a traversal schedule (AttentionPlan), not a weight distribution.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
from dataclasses import dataclass
|
||
from typing import Tuple
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class CoherenceBudget:
|
||
"""Explicit resource envelope for a single cognitive cycle."""
|
||
total_capacity: float
|
||
committed: float # units allocated to active traversal
|
||
reserve: float # units held for inhibition / correction passes
|
||
spent: float = 0.0 # units consumed so far this cycle
|
||
|
||
def __post_init__(self) -> None:
|
||
if self.committed + self.reserve > self.total_capacity:
|
||
raise ValueError("committed + reserve must not exceed total_capacity")
|
||
|
||
@property
|
||
def available(self) -> float:
|
||
return self.committed - self.spent
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class TraversalStep:
|
||
"""A single step in the attention traversal schedule."""
|
||
region_id: str
|
||
depth: float # how deeply to activate this region (0.0–1.0)
|
||
duration: float # how many sub-cycles to hold activation
|
||
cost: float # CoherenceBudget units consumed by this step
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class AttentionPlan:
|
||
"""Ordered traversal schedule produced by AttentionOperator."""
|
||
steps: Tuple[TraversalStep, ...]
|
||
total_cost: float
|
||
cycle_index: int
|
||
|
||
|
||
class AttentionOperator:
|
||
"""Produces an AttentionPlan from a SalienceMap and CoherenceBudget."""
|
||
|
||
def plan(self, salience_map, budget: CoherenceBudget, cycle_index: int) -> AttentionPlan:
|
||
steps: list[TraversalStep] = []
|
||
spent = 0.0
|
||
max_curvature = max(
|
||
(float(entry.curvature_magnitude) for entry in salience_map.entries),
|
||
default=0.0,
|
||
)
|
||
if max_curvature <= 0.0:
|
||
return AttentionPlan(steps=(), total_cost=0.0, cycle_index=cycle_index)
|
||
for entry in salience_map.entries:
|
||
depth = max(0.0, min(1.0, float(entry.curvature_magnitude) / max_curvature))
|
||
duration = max(1.0, float(entry.influence_radius))
|
||
cost = depth * duration
|
||
if spent + cost > budget.available:
|
||
break
|
||
steps.append(
|
||
TraversalStep(
|
||
region_id=entry.region_id,
|
||
depth=depth,
|
||
duration=duration,
|
||
cost=cost,
|
||
)
|
||
)
|
||
spent += cost
|
||
return AttentionPlan(steps=tuple(steps), total_cost=spent, cycle_index=cycle_index)
|