Skip to content

Commit 3103b00

Browse files
Copilotfermga
andcommitted
Implement canonical vibrational metabolism for THOL operator
Co-authored-by: fermga <203334638+fermga@users.noreply.github.com>
1 parent 04e95fd commit 3103b00

File tree

4 files changed

+733
-15
lines changed

4 files changed

+733
-15
lines changed

src/tnfr/config/defaults_core.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ class CoreDefaults:
135135
HISTORY_MAXLEN: int = 0
136136
NODAL_EQUATION_CLIP_AWARE: bool = True
137137
NODAL_EQUATION_TOLERANCE: float = 1e-9
138+
# THOL (Self-organization) vibrational metabolism parameters
139+
THOL_METABOLIC_ENABLED: bool = True
140+
THOL_METABOLIC_GRADIENT_WEIGHT: float = 0.15
141+
THOL_METABOLIC_COMPLEXITY_WEIGHT: float = 0.10
142+
THOL_BIFURCATION_THRESHOLD: float = 0.1
138143

139144

140145
@dataclass(frozen=True, slots=True)

src/tnfr/operators/definitions.py

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,6 +2429,19 @@ class SelfOrganization(Operator):
24292429
- **Vibrational metabolism**: Digests external experience into internal structure
24302430
- **Complexity emergence**: Engine of novelty and evolution in TNFR
24312431
2432+
**Vibrational Metabolism (Canonical THOL):**
2433+
2434+
THOL implements the metabolic principle: capturing network vibrational signals
2435+
(EPI gradients, phase variance) and transforming them into internal structure
2436+
(sub-EPIs). This ensures that bifurcation reflects not only internal acceleration
2437+
but also the network's coherence field.
2438+
2439+
Metabolic formula: ``sub-EPI = base + gradient*w₁ + variance*w₂``
2440+
2441+
- If node has neighbors: Captures and metabolizes network signals
2442+
- If node is isolated: Falls back to pure internal bifurcation
2443+
- Configurable via ``THOL_METABOLIC_ENABLED`` and weight parameters
2444+
24322445
Use Cases: Emergence processes, bifurcation events, creative reorganization, complex
24332446
system evolution, spontaneous order generation.
24342447
@@ -2538,11 +2551,15 @@ def _compute_epi_acceleration(self, G: TNFRGraph, node: Any) -> float:
25382551
def _spawn_sub_epi(
25392552
self, G: TNFRGraph, node: Any, d2_epi: float, tau: float
25402553
) -> None:
2541-
"""Generate sub-EPI through bifurcation.
2554+
"""Generate sub-EPI through bifurcation with vibrational metabolism.
25422555
2543-
When acceleration exceeds threshold, creates nested sub-structure
2544-
that inherits properties from parent while maintaining operational
2545-
fractality.
2556+
When acceleration exceeds threshold, creates nested sub-structure that:
2557+
1. Captures network vibrational signals (metabolic perception)
2558+
2. Metabolizes signals into sub-EPI magnitude (digestion)
2559+
3. Inherits properties from parent while integrating field context
2560+
2561+
This implements canonical THOL: "reorganizes external experience into
2562+
internal structure without external instruction".
25462563
25472564
Parameters
25482565
----------
@@ -2557,29 +2574,57 @@ def _spawn_sub_epi(
25572574
"""
25582575
from ..alias import get_attr, set_attr
25592576
from ..constants.aliases import ALIAS_EPI, ALIAS_VF
2577+
from .metabolism import capture_network_signals, metabolize_signals_into_subepi
25602578

25612579
# Get current node state
25622580
parent_epi = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
25632581
parent_vf = float(get_attr(G.nodes[node], ALIAS_VF, 1.0))
25642582

2565-
# Calculate sub-EPI magnitude using canonical scaling factor
2566-
sub_epi_value = parent_epi * _THOL_SUB_EPI_SCALING
2583+
# Check if vibrational metabolism is enabled
2584+
metabolic_enabled = G.graph.get("THOL_METABOLIC_ENABLED", True)
2585+
2586+
# CANONICAL METABOLISM: Capture network context
2587+
network_signals = None
2588+
if metabolic_enabled:
2589+
network_signals = capture_network_signals(G, node)
2590+
2591+
# Get metabolic weights from graph config
2592+
gradient_weight = float(
2593+
G.graph.get("THOL_METABOLIC_GRADIENT_WEIGHT", 0.15)
2594+
)
2595+
complexity_weight = float(
2596+
G.graph.get("THOL_METABOLIC_COMPLEXITY_WEIGHT", 0.10)
2597+
)
2598+
2599+
# CANONICAL METABOLISM: Digest signals into sub-EPI
2600+
sub_epi_value = metabolize_signals_into_subepi(
2601+
parent_epi=parent_epi,
2602+
signals=network_signals if metabolic_enabled else None,
2603+
d2_epi=d2_epi,
2604+
scaling_factor=_THOL_SUB_EPI_SCALING,
2605+
gradient_weight=gradient_weight,
2606+
complexity_weight=complexity_weight,
2607+
)
25672608

25682609
# Store sub-EPI in node's sub_epis list
25692610
sub_epis = G.nodes[node].get("sub_epis", [])
25702611

25712612
# Get current timestamp from glyph history length
25722613
timestamp = len(G.nodes[node].get("glyph_history", []))
25732614

2574-
sub_epis.append(
2575-
{
2576-
"epi": sub_epi_value,
2577-
"vf": parent_vf,
2578-
"timestamp": timestamp,
2579-
"d2_epi": d2_epi,
2580-
"tau": tau,
2581-
}
2582-
)
2615+
# Store sub-EPI with metabolic metadata
2616+
sub_epi_record = {
2617+
"epi": sub_epi_value,
2618+
"vf": parent_vf,
2619+
"timestamp": timestamp,
2620+
"d2_epi": d2_epi,
2621+
"tau": tau,
2622+
# NEW: Metabolic metadata
2623+
"metabolized": network_signals is not None and metabolic_enabled,
2624+
"network_signals": network_signals,
2625+
}
2626+
2627+
sub_epis.append(sub_epi_record)
25832628
G.nodes[node]["sub_epis"] = sub_epis
25842629

25852630
# Increment parent EPI using canonical emergence contribution

src/tnfr/operators/metabolism.py

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
"""Vibrational metabolism functions for THOL (Self-organization) operator.
2+
3+
Implements canonical pattern digestion: capturing external network signals
4+
and transforming them into internal structural reorganization (ΔNFR and sub-EPIs).
5+
6+
TNFR Canonical Principle
7+
-------------------------
8+
From "El pulso que nos atraviesa" (TNFR Manual, §2.2.10):
9+
10+
"THOL es el glifo de la autoorganización activa. No necesita intervención
11+
externa, ni programación, ni control — su función es reorganizar la forma
12+
desde dentro, en respuesta a la coherencia vibracional del campo."
13+
14+
"THOL no es una propiedad, es una dinámica. No es un atributo de lo vivo,
15+
es lo que hace que algo esté vivo. La autoorganización no es espontaneidad
16+
aleatoria, es resonancia estructurada desde el interior del nodo."
17+
18+
This module operationalizes vibrational metabolism:
19+
1. **Capture**: Sample network environment (EPI gradient, phase variance, coupling)
20+
2. **Metabolize**: Transform external patterns into internal structure (sub-EPIs)
21+
3. **Integrate**: Sub-EPIs reflect both internal acceleration AND network context
22+
23+
Metabolic Formula
24+
-----------------
25+
sub-EPI = base_internal + network_contribution + complexity_bonus
26+
27+
Where:
28+
- base_internal: parent_epi * scaling_factor (internal bifurcation)
29+
- network_contribution: epi_gradient * weight (external pressure)
30+
- complexity_bonus: phase_variance * weight (field complexity)
31+
"""
32+
33+
from __future__ import annotations
34+
35+
import math
36+
from typing import TYPE_CHECKING, Any
37+
38+
if TYPE_CHECKING:
39+
from ..types import NodeId, TNFRGraph
40+
41+
from ..alias import get_attr
42+
from ..constants.aliases import ALIAS_DNFR, ALIAS_EPI, ALIAS_THETA, ALIAS_VF
43+
from ..utils import get_numpy
44+
45+
__all__ = [
46+
"capture_network_signals",
47+
"metabolize_signals_into_subepi",
48+
]
49+
50+
51+
def capture_network_signals(G: TNFRGraph, node: NodeId) -> dict[str, Any] | None:
52+
"""Capture external vibrational patterns from coupled neighbors.
53+
54+
This function implements the "perception" phase of THOL's vibrational metabolism.
55+
It samples the network environment around the target node, computing structural
56+
gradients, phase variance, and coupling strength.
57+
58+
Parameters
59+
----------
60+
G : TNFRGraph
61+
Graph containing the node and its network context
62+
node : NodeId
63+
Node performing metabolic capture
64+
65+
Returns
66+
-------
67+
dict | None
68+
Network signal structure containing:
69+
- epi_gradient: Difference between mean neighbor EPI and node EPI
70+
- phase_variance: Variance of neighbor phases (instability indicator)
71+
- neighbor_count: Number of coupled neighbors
72+
- coupling_strength_mean: Average phase alignment with neighbors
73+
- mean_neighbor_epi: Mean EPI value of neighbors
74+
Returns None if node has no neighbors (isolated metabolism).
75+
76+
Notes
77+
-----
78+
TNFR Principle: THOL doesn't operate in vacuum—it metabolizes the network's
79+
vibrational field. EPI gradient represents "structural pressure" from environment.
80+
Phase variance indicates "complexity" of external patterns to digest.
81+
82+
Examples
83+
--------
84+
>>> # Node with coherent neighbors (low variance)
85+
>>> signals = capture_network_signals(G, node)
86+
>>> signals["phase_variance"] # Low = stable field
87+
0.02
88+
89+
>>> # Node in dissonant field (high variance)
90+
>>> signals = capture_network_signals(G_dissonant, node)
91+
>>> signals["phase_variance"] # High = complex field
92+
0.45
93+
"""
94+
np = get_numpy()
95+
96+
neighbors = list(G.neighbors(node))
97+
if not neighbors:
98+
return None
99+
100+
node_epi = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
101+
node_theta = float(get_attr(G.nodes[node], ALIAS_THETA, 0.0))
102+
103+
# Aggregate neighbor states
104+
neighbor_epis = []
105+
neighbor_thetas = []
106+
coupling_strengths = []
107+
108+
for n in neighbors:
109+
n_epi = float(get_attr(G.nodes[n], ALIAS_EPI, 0.0))
110+
n_theta = float(get_attr(G.nodes[n], ALIAS_THETA, 0.0))
111+
112+
neighbor_epis.append(n_epi)
113+
neighbor_thetas.append(n_theta)
114+
115+
# Coupling strength based on phase alignment
116+
phase_diff = abs(n_theta - node_theta)
117+
# Normalize to [0, π]
118+
if phase_diff > math.pi:
119+
phase_diff = 2 * math.pi - phase_diff
120+
coupling_strength = 1.0 - (phase_diff / math.pi)
121+
coupling_strengths.append(coupling_strength)
122+
123+
# Compute structural gradients
124+
mean_neighbor_epi = float(np.mean(neighbor_epis))
125+
epi_gradient = mean_neighbor_epi - node_epi
126+
127+
# Phase variance (complexity/dissonance indicator)
128+
phase_variance = float(np.var(neighbor_thetas))
129+
130+
# Mean coupling strength
131+
coupling_strength_mean = float(np.mean(coupling_strengths))
132+
133+
return {
134+
"epi_gradient": epi_gradient,
135+
"phase_variance": phase_variance,
136+
"neighbor_count": len(neighbors),
137+
"coupling_strength_mean": coupling_strength_mean,
138+
"mean_neighbor_epi": mean_neighbor_epi,
139+
}
140+
141+
142+
def metabolize_signals_into_subepi(
143+
parent_epi: float,
144+
signals: dict[str, Any] | None,
145+
d2_epi: float,
146+
scaling_factor: float = 0.25,
147+
gradient_weight: float = 0.15,
148+
complexity_weight: float = 0.10,
149+
) -> float:
150+
"""Transform external signals into sub-EPI structure through metabolism.
151+
152+
This function implements the "digestion" phase of THOL's vibrational metabolism.
153+
It combines internal acceleration (d²EPI/dt²) with external network pressure
154+
to compute the magnitude of emergent sub-EPI.
155+
156+
Parameters
157+
----------
158+
parent_epi : float
159+
Current EPI magnitude of parent node
160+
signals : dict | None
161+
Network signals captured from environment (from capture_network_signals).
162+
If None, falls back to internal bifurcation only.
163+
d2_epi : float
164+
Internal structural acceleration (∂²EPI/∂t²)
165+
scaling_factor : float, default 0.25
166+
Canonical THOL sub-EPI scaling (0.25 = 25% of parent)
167+
gradient_weight : float, default 0.15
168+
Weight for external EPI gradient contribution
169+
complexity_weight : float, default 0.10
170+
Weight for phase variance complexity bonus
171+
172+
Returns
173+
-------
174+
float
175+
Metabolized sub-EPI magnitude, bounded to [0, 1.0]
176+
177+
Notes
178+
-----
179+
TNFR Metabolic Formula:
180+
181+
sub-EPI = base_internal + network_contribution + complexity_bonus
182+
183+
Where:
184+
- base_internal: parent_epi * scaling_factor (internal bifurcation)
185+
- network_contribution: epi_gradient * weight (external pressure)
186+
- complexity_bonus: phase_variance * weight (field complexity)
187+
188+
This reflects canonical principle: "THOL reorganizes external experience
189+
into internal structure without external instruction" (Manual TNFR, p. 112).
190+
191+
Examples
192+
--------
193+
>>> # Internal bifurcation only (isolated node)
194+
>>> metabolize_signals_into_subepi(0.60, None, d2_epi=0.15)
195+
0.15
196+
197+
>>> # Metabolizing network pressure
198+
>>> signals = {"epi_gradient": 0.20, "phase_variance": 0.10, ...}
199+
>>> metabolize_signals_into_subepi(0.60, signals, d2_epi=0.15)
200+
0.21 # Enhanced by network context
201+
"""
202+
np = get_numpy()
203+
204+
# Base: Internal bifurcation (existing behavior)
205+
base_sub_epi = parent_epi * scaling_factor
206+
207+
# If isolated, return internal bifurcation only
208+
if signals is None:
209+
return float(np.clip(base_sub_epi, 0.0, 1.0))
210+
211+
# Network contribution: EPI gradient pressure
212+
network_contribution = signals["epi_gradient"] * gradient_weight
213+
214+
# Complexity bonus: Phase variance indicates rich field to metabolize
215+
complexity_bonus = signals["phase_variance"] * complexity_weight
216+
217+
# Combine internal + external
218+
metabolized_epi = base_sub_epi + network_contribution + complexity_bonus
219+
220+
# Structural bounds [0, 1]
221+
return float(np.clip(metabolized_epi, 0.0, 1.0))

0 commit comments

Comments
 (0)