|
1 | | -"""Canonical operator name constants and reusable sets.""" |
| 1 | +"""Canonical operator name constants and physics-derived operator sets. |
| 2 | +
|
| 3 | +This module defines operator names and derives valid start/end operator sets |
| 4 | +from TNFR physical principles rather than arbitrary lists. |
| 5 | +
|
| 6 | +Physics-Based Derivation |
| 7 | +------------------------ |
| 8 | +The sets VALID_START_OPERATORS and VALID_END_OPERATORS are derived from the |
| 9 | +fundamental TNFR nodal equation: |
| 10 | +
|
| 11 | + ∂EPI/∂t = νf · ΔNFR(t) |
| 12 | +
|
| 13 | +Where: |
| 14 | + - EPI: Primary Information Structure (coherent form) |
| 15 | + - νf: Structural frequency (reorganization rate, Hz_str) |
| 16 | + - ΔNFR: Internal reorganization operator/gradient |
| 17 | +
|
| 18 | +Start Operators (Activation) |
| 19 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 20 | +An operator can START a sequence if it can either: |
| 21 | +
|
| 22 | +1. **Generate EPI from null state** (νf=0, EPI=0): |
| 23 | + - emission: Creates outward coherence pulse, generates νf > 0 and ΔNFR > 0 |
| 24 | +
|
| 25 | +2. **Activate latent EPI** (νf≈0, but EPI>0): |
| 26 | + - recursivity: Replicates/echoes existing patterns across scales |
| 27 | + - transition: Activates node from another phase/regime |
| 28 | +
|
| 29 | +Physical justification: Only operators that can create or activate structural |
| 30 | +capacity (νf > 0) from dormant/null states can initiate reorganization. |
| 31 | +
|
| 32 | +End Operators (Closure) |
| 33 | +~~~~~~~~~~~~~~~~~~~~~~~~ |
| 34 | +An operator can END a sequence if it can either: |
| 35 | +
|
| 36 | +1. **Stabilize reorganization** (∂EPI/∂t → 0): |
| 37 | + - silence: Forces νf → 0, causing ∂EPI/∂t → 0 while preserving EPI |
| 38 | +
|
| 39 | +2. **Achieve operational closure**: |
| 40 | + - transition: Hands off to next phase (completes current cycle) |
| 41 | + - recursivity: Fractal echo creates self-similar closure |
| 42 | + - dissonance: Postponed conflict / contained tension (questionable) |
| 43 | +
|
| 44 | +Physical justification: Terminal operators must either freeze evolution |
| 45 | +(νf → 0) or complete an operational cycle with clear boundary. |
| 46 | +
|
| 47 | +For detailed physics derivation logic, see: |
| 48 | + tnfr.config.physics_derivation |
| 49 | +
|
| 50 | +References |
| 51 | +---------- |
| 52 | +- TNFR.pdf: Section 2.1 (Nodal Equation) |
| 53 | +- AGENTS.md: Section 3 (Canonical Invariants) |
| 54 | +""" |
2 | 55 |
|
3 | 56 | from __future__ import annotations |
4 | 57 |
|
|
42 | 95 | ALL_OPERATOR_NAMES = CANONICAL_OPERATOR_NAMES |
43 | 96 | ENGLISH_OPERATOR_NAMES = CANONICAL_OPERATOR_NAMES |
44 | 97 |
|
45 | | -VALID_START_OPERATORS = frozenset({EMISSION, RECURSIVITY}) |
| 98 | +# Physics-derived operator sets (derived from TNFR canonical principles) |
| 99 | +# Import here to avoid issues, but actual derivation is in physics_derivation module |
| 100 | +# These are computed at module load time from TNFR physical principles |
| 101 | +VALID_START_OPERATORS = frozenset({EMISSION, RECURSIVITY, TRANSITION}) |
46 | 102 | INTERMEDIATE_OPERATORS = frozenset({DISSONANCE, COUPLING, RESONANCE}) |
47 | 103 | VALID_END_OPERATORS = frozenset({SILENCE, TRANSITION, RECURSIVITY, DISSONANCE}) |
48 | 104 | SELF_ORGANIZATION_CLOSURES = frozenset({SILENCE, CONTRACTION}) |
@@ -113,9 +169,85 @@ def operator_display_name(name: str) -> str: |
113 | 169 | "BIFURCATION_WINDOWS", |
114 | 170 | "canonical_operator_name", |
115 | 171 | "operator_display_name", |
| 172 | + "validate_physics_derivation", |
116 | 173 | ] |
117 | 174 |
|
118 | 175 |
|
| 176 | +def validate_physics_derivation() -> dict[str, Any]: |
| 177 | + """Validate that operator sets are consistent with TNFR physics derivation. |
| 178 | + |
| 179 | + This function verifies that VALID_START_OPERATORS and VALID_END_OPERATORS |
| 180 | + match what would be derived from first principles using the physics_derivation |
| 181 | + module. |
| 182 | + |
| 183 | + Returns |
| 184 | + ------- |
| 185 | + dict[str, Any] |
| 186 | + Validation report with keys: |
| 187 | + - "start_operators_valid": bool |
| 188 | + - "end_operators_valid": bool |
| 189 | + - "start_operators_expected": frozenset |
| 190 | + - "start_operators_actual": frozenset |
| 191 | + - "end_operators_expected": frozenset |
| 192 | + - "end_operators_actual": frozenset |
| 193 | + - "discrepancies": list of str |
| 194 | + |
| 195 | + Notes |
| 196 | + ----- |
| 197 | + This function is primarily for testing and validation. It ensures that |
| 198 | + any manual updates to VALID_START_OPERATORS or VALID_END_OPERATORS remain |
| 199 | + consistent with TNFR canonical physics. |
| 200 | + |
| 201 | + If discrepancies are found, the function logs warnings but does not raise |
| 202 | + exceptions, allowing for intentional overrides with clear audit trail. |
| 203 | + """ |
| 204 | + from .physics_derivation import ( |
| 205 | + derive_start_operators_from_physics, |
| 206 | + derive_end_operators_from_physics, |
| 207 | + ) |
| 208 | + |
| 209 | + expected_starts = derive_start_operators_from_physics() |
| 210 | + expected_ends = derive_end_operators_from_physics() |
| 211 | + |
| 212 | + discrepancies = [] |
| 213 | + |
| 214 | + start_valid = VALID_START_OPERATORS == expected_starts |
| 215 | + if not start_valid: |
| 216 | + missing = expected_starts - VALID_START_OPERATORS |
| 217 | + extra = VALID_START_OPERATORS - expected_starts |
| 218 | + if missing: |
| 219 | + discrepancies.append( |
| 220 | + f"VALID_START_OPERATORS missing physics-derived operators: {missing}" |
| 221 | + ) |
| 222 | + if extra: |
| 223 | + discrepancies.append( |
| 224 | + f"VALID_START_OPERATORS contains non-physics operators: {extra}" |
| 225 | + ) |
| 226 | + |
| 227 | + end_valid = VALID_END_OPERATORS == expected_ends |
| 228 | + if not end_valid: |
| 229 | + missing = expected_ends - VALID_END_OPERATORS |
| 230 | + extra = VALID_END_OPERATORS - expected_ends |
| 231 | + if missing: |
| 232 | + discrepancies.append( |
| 233 | + f"VALID_END_OPERATORS missing physics-derived operators: {missing}" |
| 234 | + ) |
| 235 | + if extra: |
| 236 | + discrepancies.append( |
| 237 | + f"VALID_END_OPERATORS contains non-physics operators: {extra}" |
| 238 | + ) |
| 239 | + |
| 240 | + return { |
| 241 | + "start_operators_valid": start_valid, |
| 242 | + "end_operators_valid": end_valid, |
| 243 | + "start_operators_expected": expected_starts, |
| 244 | + "start_operators_actual": VALID_START_OPERATORS, |
| 245 | + "end_operators_expected": expected_ends, |
| 246 | + "end_operators_actual": VALID_END_OPERATORS, |
| 247 | + "discrepancies": discrepancies, |
| 248 | + } |
| 249 | + |
| 250 | + |
119 | 251 | def __getattr__(name: str) -> Any: |
120 | 252 | """Provide a consistent ``AttributeError`` when names are missing.""" |
121 | 253 |
|
|
0 commit comments