core/core/physics/attention.py

74 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""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.01.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)