tnfr 4.5.2__py3-none-any.whl → 8.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tnfr might be problematic. Click here for more details.

Files changed (365) hide show
  1. tnfr/__init__.py +334 -50
  2. tnfr/__init__.pyi +33 -0
  3. tnfr/_compat.py +10 -0
  4. tnfr/_generated_version.py +34 -0
  5. tnfr/_version.py +49 -0
  6. tnfr/_version.pyi +7 -0
  7. tnfr/alias.py +214 -37
  8. tnfr/alias.pyi +108 -0
  9. tnfr/backends/__init__.py +354 -0
  10. tnfr/backends/jax_backend.py +173 -0
  11. tnfr/backends/numpy_backend.py +238 -0
  12. tnfr/backends/optimized_numpy.py +420 -0
  13. tnfr/backends/torch_backend.py +408 -0
  14. tnfr/cache.py +149 -556
  15. tnfr/cache.pyi +13 -0
  16. tnfr/cli/__init__.py +51 -16
  17. tnfr/cli/__init__.pyi +26 -0
  18. tnfr/cli/arguments.py +344 -32
  19. tnfr/cli/arguments.pyi +29 -0
  20. tnfr/cli/execution.py +676 -50
  21. tnfr/cli/execution.pyi +70 -0
  22. tnfr/cli/interactive_validator.py +614 -0
  23. tnfr/cli/utils.py +18 -3
  24. tnfr/cli/utils.pyi +7 -0
  25. tnfr/cli/validate.py +236 -0
  26. tnfr/compat/__init__.py +85 -0
  27. tnfr/compat/dataclass.py +136 -0
  28. tnfr/compat/jsonschema_stub.py +61 -0
  29. tnfr/compat/matplotlib_stub.py +73 -0
  30. tnfr/compat/numpy_stub.py +155 -0
  31. tnfr/config/__init__.py +224 -0
  32. tnfr/config/__init__.pyi +10 -0
  33. tnfr/{constants_glyphs.py → config/constants.py} +26 -20
  34. tnfr/config/constants.pyi +12 -0
  35. tnfr/config/defaults.py +54 -0
  36. tnfr/{constants/core.py → config/defaults_core.py} +59 -6
  37. tnfr/config/defaults_init.py +33 -0
  38. tnfr/config/defaults_metric.py +104 -0
  39. tnfr/config/feature_flags.py +81 -0
  40. tnfr/config/feature_flags.pyi +16 -0
  41. tnfr/config/glyph_constants.py +31 -0
  42. tnfr/config/init.py +77 -0
  43. tnfr/config/init.pyi +8 -0
  44. tnfr/config/operator_names.py +254 -0
  45. tnfr/config/operator_names.pyi +36 -0
  46. tnfr/config/physics_derivation.py +354 -0
  47. tnfr/config/presets.py +83 -0
  48. tnfr/config/presets.pyi +7 -0
  49. tnfr/config/security.py +927 -0
  50. tnfr/config/thresholds.py +114 -0
  51. tnfr/config/tnfr_config.py +498 -0
  52. tnfr/constants/__init__.py +51 -133
  53. tnfr/constants/__init__.pyi +92 -0
  54. tnfr/constants/aliases.py +33 -0
  55. tnfr/constants/aliases.pyi +27 -0
  56. tnfr/constants/init.py +3 -1
  57. tnfr/constants/init.pyi +12 -0
  58. tnfr/constants/metric.py +9 -15
  59. tnfr/constants/metric.pyi +19 -0
  60. tnfr/core/__init__.py +33 -0
  61. tnfr/core/container.py +226 -0
  62. tnfr/core/default_implementations.py +329 -0
  63. tnfr/core/interfaces.py +279 -0
  64. tnfr/dynamics/__init__.py +213 -633
  65. tnfr/dynamics/__init__.pyi +83 -0
  66. tnfr/dynamics/adaptation.py +267 -0
  67. tnfr/dynamics/adaptation.pyi +7 -0
  68. tnfr/dynamics/adaptive_sequences.py +189 -0
  69. tnfr/dynamics/adaptive_sequences.pyi +14 -0
  70. tnfr/dynamics/aliases.py +23 -0
  71. tnfr/dynamics/aliases.pyi +19 -0
  72. tnfr/dynamics/bifurcation.py +232 -0
  73. tnfr/dynamics/canonical.py +229 -0
  74. tnfr/dynamics/canonical.pyi +48 -0
  75. tnfr/dynamics/coordination.py +385 -0
  76. tnfr/dynamics/coordination.pyi +25 -0
  77. tnfr/dynamics/dnfr.py +2699 -398
  78. tnfr/dynamics/dnfr.pyi +26 -0
  79. tnfr/dynamics/dynamic_limits.py +225 -0
  80. tnfr/dynamics/feedback.py +252 -0
  81. tnfr/dynamics/feedback.pyi +24 -0
  82. tnfr/dynamics/fused_dnfr.py +454 -0
  83. tnfr/dynamics/homeostasis.py +157 -0
  84. tnfr/dynamics/homeostasis.pyi +14 -0
  85. tnfr/dynamics/integrators.py +496 -102
  86. tnfr/dynamics/integrators.pyi +36 -0
  87. tnfr/dynamics/learning.py +310 -0
  88. tnfr/dynamics/learning.pyi +33 -0
  89. tnfr/dynamics/metabolism.py +254 -0
  90. tnfr/dynamics/nbody.py +796 -0
  91. tnfr/dynamics/nbody_tnfr.py +783 -0
  92. tnfr/dynamics/propagation.py +326 -0
  93. tnfr/dynamics/runtime.py +908 -0
  94. tnfr/dynamics/runtime.pyi +77 -0
  95. tnfr/dynamics/sampling.py +10 -5
  96. tnfr/dynamics/sampling.pyi +7 -0
  97. tnfr/dynamics/selectors.py +711 -0
  98. tnfr/dynamics/selectors.pyi +85 -0
  99. tnfr/dynamics/structural_clip.py +207 -0
  100. tnfr/errors/__init__.py +37 -0
  101. tnfr/errors/contextual.py +492 -0
  102. tnfr/execution.py +77 -55
  103. tnfr/execution.pyi +45 -0
  104. tnfr/extensions/__init__.py +205 -0
  105. tnfr/extensions/__init__.pyi +18 -0
  106. tnfr/extensions/base.py +173 -0
  107. tnfr/extensions/base.pyi +35 -0
  108. tnfr/extensions/business/__init__.py +71 -0
  109. tnfr/extensions/business/__init__.pyi +11 -0
  110. tnfr/extensions/business/cookbook.py +88 -0
  111. tnfr/extensions/business/cookbook.pyi +8 -0
  112. tnfr/extensions/business/health_analyzers.py +202 -0
  113. tnfr/extensions/business/health_analyzers.pyi +9 -0
  114. tnfr/extensions/business/patterns.py +183 -0
  115. tnfr/extensions/business/patterns.pyi +8 -0
  116. tnfr/extensions/medical/__init__.py +73 -0
  117. tnfr/extensions/medical/__init__.pyi +11 -0
  118. tnfr/extensions/medical/cookbook.py +88 -0
  119. tnfr/extensions/medical/cookbook.pyi +8 -0
  120. tnfr/extensions/medical/health_analyzers.py +181 -0
  121. tnfr/extensions/medical/health_analyzers.pyi +9 -0
  122. tnfr/extensions/medical/patterns.py +163 -0
  123. tnfr/extensions/medical/patterns.pyi +8 -0
  124. tnfr/flatten.py +29 -50
  125. tnfr/flatten.pyi +21 -0
  126. tnfr/gamma.py +66 -53
  127. tnfr/gamma.pyi +36 -0
  128. tnfr/glyph_history.py +144 -57
  129. tnfr/glyph_history.pyi +35 -0
  130. tnfr/glyph_runtime.py +19 -0
  131. tnfr/glyph_runtime.pyi +8 -0
  132. tnfr/immutable.py +70 -30
  133. tnfr/immutable.pyi +36 -0
  134. tnfr/initialization.py +22 -16
  135. tnfr/initialization.pyi +65 -0
  136. tnfr/io.py +5 -241
  137. tnfr/io.pyi +13 -0
  138. tnfr/locking.pyi +7 -0
  139. tnfr/mathematics/__init__.py +79 -0
  140. tnfr/mathematics/backend.py +453 -0
  141. tnfr/mathematics/backend.pyi +99 -0
  142. tnfr/mathematics/dynamics.py +408 -0
  143. tnfr/mathematics/dynamics.pyi +90 -0
  144. tnfr/mathematics/epi.py +391 -0
  145. tnfr/mathematics/epi.pyi +65 -0
  146. tnfr/mathematics/generators.py +242 -0
  147. tnfr/mathematics/generators.pyi +29 -0
  148. tnfr/mathematics/metrics.py +119 -0
  149. tnfr/mathematics/metrics.pyi +16 -0
  150. tnfr/mathematics/operators.py +239 -0
  151. tnfr/mathematics/operators.pyi +59 -0
  152. tnfr/mathematics/operators_factory.py +124 -0
  153. tnfr/mathematics/operators_factory.pyi +11 -0
  154. tnfr/mathematics/projection.py +87 -0
  155. tnfr/mathematics/projection.pyi +33 -0
  156. tnfr/mathematics/runtime.py +182 -0
  157. tnfr/mathematics/runtime.pyi +64 -0
  158. tnfr/mathematics/spaces.py +256 -0
  159. tnfr/mathematics/spaces.pyi +83 -0
  160. tnfr/mathematics/transforms.py +305 -0
  161. tnfr/mathematics/transforms.pyi +62 -0
  162. tnfr/metrics/__init__.py +47 -9
  163. tnfr/metrics/__init__.pyi +20 -0
  164. tnfr/metrics/buffer_cache.py +163 -0
  165. tnfr/metrics/buffer_cache.pyi +24 -0
  166. tnfr/metrics/cache_utils.py +214 -0
  167. tnfr/metrics/coherence.py +1510 -330
  168. tnfr/metrics/coherence.pyi +129 -0
  169. tnfr/metrics/common.py +23 -16
  170. tnfr/metrics/common.pyi +35 -0
  171. tnfr/metrics/core.py +251 -36
  172. tnfr/metrics/core.pyi +13 -0
  173. tnfr/metrics/diagnosis.py +709 -110
  174. tnfr/metrics/diagnosis.pyi +86 -0
  175. tnfr/metrics/emergence.py +245 -0
  176. tnfr/metrics/export.py +60 -18
  177. tnfr/metrics/export.pyi +7 -0
  178. tnfr/metrics/glyph_timing.py +233 -43
  179. tnfr/metrics/glyph_timing.pyi +81 -0
  180. tnfr/metrics/learning_metrics.py +280 -0
  181. tnfr/metrics/learning_metrics.pyi +21 -0
  182. tnfr/metrics/phase_coherence.py +351 -0
  183. tnfr/metrics/phase_compatibility.py +349 -0
  184. tnfr/metrics/reporting.py +63 -28
  185. tnfr/metrics/reporting.pyi +25 -0
  186. tnfr/metrics/sense_index.py +1126 -43
  187. tnfr/metrics/sense_index.pyi +9 -0
  188. tnfr/metrics/trig.py +215 -23
  189. tnfr/metrics/trig.pyi +13 -0
  190. tnfr/metrics/trig_cache.py +148 -24
  191. tnfr/metrics/trig_cache.pyi +10 -0
  192. tnfr/multiscale/__init__.py +32 -0
  193. tnfr/multiscale/hierarchical.py +517 -0
  194. tnfr/node.py +646 -140
  195. tnfr/node.pyi +139 -0
  196. tnfr/observers.py +160 -45
  197. tnfr/observers.pyi +31 -0
  198. tnfr/ontosim.py +23 -19
  199. tnfr/ontosim.pyi +28 -0
  200. tnfr/operators/__init__.py +1358 -106
  201. tnfr/operators/__init__.pyi +31 -0
  202. tnfr/operators/algebra.py +277 -0
  203. tnfr/operators/canonical_patterns.py +420 -0
  204. tnfr/operators/cascade.py +267 -0
  205. tnfr/operators/cycle_detection.py +358 -0
  206. tnfr/operators/definitions.py +4108 -0
  207. tnfr/operators/definitions.pyi +78 -0
  208. tnfr/operators/grammar.py +1164 -0
  209. tnfr/operators/grammar.pyi +140 -0
  210. tnfr/operators/hamiltonian.py +710 -0
  211. tnfr/operators/health_analyzer.py +809 -0
  212. tnfr/operators/jitter.py +107 -38
  213. tnfr/operators/jitter.pyi +11 -0
  214. tnfr/operators/lifecycle.py +314 -0
  215. tnfr/operators/metabolism.py +618 -0
  216. tnfr/operators/metrics.py +2138 -0
  217. tnfr/operators/network_analysis/__init__.py +27 -0
  218. tnfr/operators/network_analysis/source_detection.py +186 -0
  219. tnfr/operators/nodal_equation.py +395 -0
  220. tnfr/operators/pattern_detection.py +660 -0
  221. tnfr/operators/patterns.py +669 -0
  222. tnfr/operators/postconditions/__init__.py +38 -0
  223. tnfr/operators/postconditions/mutation.py +236 -0
  224. tnfr/operators/preconditions/__init__.py +1226 -0
  225. tnfr/operators/preconditions/coherence.py +305 -0
  226. tnfr/operators/preconditions/dissonance.py +236 -0
  227. tnfr/operators/preconditions/emission.py +128 -0
  228. tnfr/operators/preconditions/mutation.py +580 -0
  229. tnfr/operators/preconditions/reception.py +125 -0
  230. tnfr/operators/preconditions/resonance.py +364 -0
  231. tnfr/operators/registry.py +74 -0
  232. tnfr/operators/registry.pyi +9 -0
  233. tnfr/operators/remesh.py +1415 -91
  234. tnfr/operators/remesh.pyi +26 -0
  235. tnfr/operators/structural_units.py +268 -0
  236. tnfr/operators/unified_grammar.py +105 -0
  237. tnfr/parallel/__init__.py +54 -0
  238. tnfr/parallel/auto_scaler.py +234 -0
  239. tnfr/parallel/distributed.py +384 -0
  240. tnfr/parallel/engine.py +238 -0
  241. tnfr/parallel/gpu_engine.py +420 -0
  242. tnfr/parallel/monitoring.py +248 -0
  243. tnfr/parallel/partitioner.py +459 -0
  244. tnfr/py.typed +0 -0
  245. tnfr/recipes/__init__.py +22 -0
  246. tnfr/recipes/cookbook.py +743 -0
  247. tnfr/rng.py +75 -151
  248. tnfr/rng.pyi +26 -0
  249. tnfr/schemas/__init__.py +8 -0
  250. tnfr/schemas/grammar.json +94 -0
  251. tnfr/sdk/__init__.py +107 -0
  252. tnfr/sdk/__init__.pyi +19 -0
  253. tnfr/sdk/adaptive_system.py +173 -0
  254. tnfr/sdk/adaptive_system.pyi +21 -0
  255. tnfr/sdk/builders.py +370 -0
  256. tnfr/sdk/builders.pyi +51 -0
  257. tnfr/sdk/fluent.py +1121 -0
  258. tnfr/sdk/fluent.pyi +74 -0
  259. tnfr/sdk/templates.py +342 -0
  260. tnfr/sdk/templates.pyi +41 -0
  261. tnfr/sdk/utils.py +341 -0
  262. tnfr/secure_config.py +46 -0
  263. tnfr/security/__init__.py +70 -0
  264. tnfr/security/database.py +514 -0
  265. tnfr/security/subprocess.py +503 -0
  266. tnfr/security/validation.py +290 -0
  267. tnfr/selector.py +59 -22
  268. tnfr/selector.pyi +19 -0
  269. tnfr/sense.py +92 -67
  270. tnfr/sense.pyi +23 -0
  271. tnfr/services/__init__.py +17 -0
  272. tnfr/services/orchestrator.py +325 -0
  273. tnfr/sparse/__init__.py +39 -0
  274. tnfr/sparse/representations.py +492 -0
  275. tnfr/structural.py +639 -263
  276. tnfr/structural.pyi +83 -0
  277. tnfr/telemetry/__init__.py +35 -0
  278. tnfr/telemetry/cache_metrics.py +226 -0
  279. tnfr/telemetry/cache_metrics.pyi +64 -0
  280. tnfr/telemetry/nu_f.py +422 -0
  281. tnfr/telemetry/nu_f.pyi +108 -0
  282. tnfr/telemetry/verbosity.py +36 -0
  283. tnfr/telemetry/verbosity.pyi +15 -0
  284. tnfr/tokens.py +2 -4
  285. tnfr/tokens.pyi +36 -0
  286. tnfr/tools/__init__.py +20 -0
  287. tnfr/tools/domain_templates.py +478 -0
  288. tnfr/tools/sequence_generator.py +846 -0
  289. tnfr/topology/__init__.py +13 -0
  290. tnfr/topology/asymmetry.py +151 -0
  291. tnfr/trace.py +300 -126
  292. tnfr/trace.pyi +42 -0
  293. tnfr/tutorials/__init__.py +38 -0
  294. tnfr/tutorials/autonomous_evolution.py +285 -0
  295. tnfr/tutorials/interactive.py +1576 -0
  296. tnfr/tutorials/structural_metabolism.py +238 -0
  297. tnfr/types.py +743 -12
  298. tnfr/types.pyi +357 -0
  299. tnfr/units.py +68 -0
  300. tnfr/units.pyi +13 -0
  301. tnfr/utils/__init__.py +282 -0
  302. tnfr/utils/__init__.pyi +215 -0
  303. tnfr/utils/cache.py +4223 -0
  304. tnfr/utils/cache.pyi +470 -0
  305. tnfr/{callback_utils.py → utils/callbacks.py} +26 -39
  306. tnfr/utils/callbacks.pyi +49 -0
  307. tnfr/utils/chunks.py +108 -0
  308. tnfr/utils/chunks.pyi +22 -0
  309. tnfr/utils/data.py +428 -0
  310. tnfr/utils/data.pyi +74 -0
  311. tnfr/utils/graph.py +85 -0
  312. tnfr/utils/graph.pyi +10 -0
  313. tnfr/utils/init.py +821 -0
  314. tnfr/utils/init.pyi +80 -0
  315. tnfr/utils/io.py +559 -0
  316. tnfr/utils/io.pyi +66 -0
  317. tnfr/{helpers → utils}/numeric.py +51 -24
  318. tnfr/utils/numeric.pyi +21 -0
  319. tnfr/validation/__init__.py +257 -0
  320. tnfr/validation/__init__.pyi +85 -0
  321. tnfr/validation/compatibility.py +460 -0
  322. tnfr/validation/compatibility.pyi +6 -0
  323. tnfr/validation/config.py +73 -0
  324. tnfr/validation/graph.py +139 -0
  325. tnfr/validation/graph.pyi +18 -0
  326. tnfr/validation/input_validation.py +755 -0
  327. tnfr/validation/invariants.py +712 -0
  328. tnfr/validation/rules.py +253 -0
  329. tnfr/validation/rules.pyi +44 -0
  330. tnfr/validation/runtime.py +279 -0
  331. tnfr/validation/runtime.pyi +28 -0
  332. tnfr/validation/sequence_validator.py +162 -0
  333. tnfr/validation/soft_filters.py +170 -0
  334. tnfr/validation/soft_filters.pyi +32 -0
  335. tnfr/validation/spectral.py +164 -0
  336. tnfr/validation/spectral.pyi +42 -0
  337. tnfr/validation/validator.py +1266 -0
  338. tnfr/validation/window.py +39 -0
  339. tnfr/validation/window.pyi +1 -0
  340. tnfr/visualization/__init__.py +98 -0
  341. tnfr/visualization/cascade_viz.py +256 -0
  342. tnfr/visualization/hierarchy.py +284 -0
  343. tnfr/visualization/sequence_plotter.py +784 -0
  344. tnfr/viz/__init__.py +60 -0
  345. tnfr/viz/matplotlib.py +278 -0
  346. tnfr/viz/matplotlib.pyi +35 -0
  347. tnfr-8.5.0.dist-info/METADATA +573 -0
  348. tnfr-8.5.0.dist-info/RECORD +353 -0
  349. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/entry_points.txt +1 -0
  350. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/licenses/LICENSE.md +1 -1
  351. tnfr/collections_utils.py +0 -300
  352. tnfr/config.py +0 -32
  353. tnfr/grammar.py +0 -344
  354. tnfr/graph_utils.py +0 -84
  355. tnfr/helpers/__init__.py +0 -71
  356. tnfr/import_utils.py +0 -228
  357. tnfr/json_utils.py +0 -162
  358. tnfr/logging_utils.py +0 -116
  359. tnfr/presets.py +0 -60
  360. tnfr/validators.py +0 -84
  361. tnfr/value_utils.py +0 -59
  362. tnfr-4.5.2.dist-info/METADATA +0 -379
  363. tnfr-4.5.2.dist-info/RECORD +0 -67
  364. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
  365. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,4108 @@
1
+ """Definitions for canonical TNFR structural operators.
2
+
3
+ Structural operators (Emission, Reception, Coherence, etc.) are the public-facing
4
+ API for applying TNFR transformations to nodes. Each operator is associated with
5
+ a specific glyph (structural symbol like AL, EN, IL, etc.) that represents the
6
+ underlying transformation.
7
+
8
+ English identifiers are the public API. Spanish wrappers were removed in
9
+ TNFR 2.0, so downstream code must import these classes directly.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import cmath
15
+ import math
16
+ import warnings
17
+ from typing import Any, ClassVar
18
+
19
+ from ..alias import get_attr
20
+ from ..config.operator_names import (
21
+ COHERENCE,
22
+ CONTRACTION,
23
+ COUPLING,
24
+ DISSONANCE,
25
+ EMISSION,
26
+ EXPANSION,
27
+ MUTATION,
28
+ RECEPTION,
29
+ RECURSIVITY,
30
+ RESONANCE,
31
+ SELF_ORGANIZATION,
32
+ SILENCE,
33
+ TRANSITION,
34
+ )
35
+ from ..constants.aliases import ALIAS_DNFR, ALIAS_EPI
36
+ from ..types import Glyph, TNFRGraph
37
+ from ..utils import get_numpy
38
+ from .registry import register_operator
39
+
40
+ __all__ = [
41
+ "Operator",
42
+ "Emission",
43
+ "Reception",
44
+ "Coherence",
45
+ "Dissonance",
46
+ "Coupling",
47
+ "Resonance",
48
+ "Silence",
49
+ "Expansion",
50
+ "Contraction",
51
+ "SelfOrganization",
52
+ "Mutation",
53
+ "Transition",
54
+ "Recursivity",
55
+ ]
56
+
57
+ # T'HOL canonical bifurcation constants
58
+ _THOL_SUB_EPI_SCALING = 0.25 # Sub-EPI is 25% of parent (first-order bifurcation)
59
+ _THOL_EMERGENCE_CONTRIBUTION = 0.1 # Parent EPI increases by 10% of sub-EPI
60
+
61
+
62
+ class Operator:
63
+ """Base class for TNFR structural operators.
64
+
65
+ Structural operators (Emission, Reception, Coherence, etc.) are the public-facing
66
+ API for applying TNFR transformations. Each operator defines a ``name`` (ASCII
67
+ identifier) and ``glyph`` (structural symbol like AL, EN, IL, etc.) that represents
68
+ the transformation. Calling an operator instance applies its structural transformation
69
+ to the target node.
70
+ """
71
+
72
+ name: ClassVar[str] = "operator"
73
+ glyph: ClassVar[Glyph | None] = None
74
+
75
+ def __call__(self, G: TNFRGraph, node: Any, **kw: Any) -> None:
76
+ """Apply the structural operator to ``node`` under canonical grammar control.
77
+
78
+ Parameters
79
+ ----------
80
+ G : TNFRGraph
81
+ Graph storing TNFR nodes, their coherence telemetry and structural
82
+ operator history.
83
+ node : Any
84
+ Identifier or object representing the target node within ``G``.
85
+ **kw : Any
86
+ Additional keyword arguments forwarded to the grammar layer.
87
+ Supported keys include:
88
+ - ``window``: constrain the grammar window
89
+ - ``validate_preconditions``: enable/disable precondition checks (default: True)
90
+ - ``collect_metrics``: enable/disable metrics collection (default: False)
91
+
92
+ Raises
93
+ ------
94
+ NotImplementedError
95
+ If ``glyph`` is :data:`None`, meaning the operator has not been
96
+ bound to a structural symbol.
97
+
98
+ Notes
99
+ -----
100
+ The invocation delegates to
101
+ :func:`tnfr.validation.apply_glyph_with_grammar`, which enforces
102
+ the TNFR grammar before activating the structural transformation. The
103
+ grammar may expand, contract or stabilise the neighbourhood so that the
104
+ operator preserves canonical closure and coherence.
105
+ """
106
+ if self.glyph is None:
107
+ raise NotImplementedError("Operator without assigned glyph")
108
+
109
+ # Optional precondition validation
110
+ validate_preconditions = kw.get("validate_preconditions", True)
111
+ if validate_preconditions and G.graph.get(
112
+ "VALIDATE_OPERATOR_PRECONDITIONS", False
113
+ ):
114
+ self._validate_preconditions(G, node)
115
+
116
+ # Capture state before operator application for metrics and validation
117
+ collect_metrics = kw.get("collect_metrics", False) or G.graph.get(
118
+ "COLLECT_OPERATOR_METRICS", False
119
+ )
120
+ validate_equation = kw.get("validate_nodal_equation", False) or G.graph.get(
121
+ "VALIDATE_NODAL_EQUATION", False
122
+ )
123
+
124
+ state_before = None
125
+ if collect_metrics or validate_equation:
126
+ state_before = self._capture_state(G, node)
127
+
128
+ from . import apply_glyph_with_grammar
129
+
130
+ apply_glyph_with_grammar(G, [node], self.glyph, kw.get("window"))
131
+
132
+ # Optional nodal equation validation (∂EPI/∂t = νf · ΔNFR(t))
133
+ if validate_equation and state_before is not None:
134
+ from ..alias import get_attr
135
+ from ..constants.aliases import ALIAS_EPI
136
+ from .nodal_equation import validate_nodal_equation
137
+
138
+ dt = float(kw.get("dt", 1.0)) # Time step, default 1.0 for discrete ops
139
+ strict = G.graph.get("NODAL_EQUATION_STRICT", False)
140
+ epi_after = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
141
+
142
+ validate_nodal_equation(
143
+ G,
144
+ node,
145
+ epi_before=state_before["epi"],
146
+ epi_after=epi_after,
147
+ dt=dt,
148
+ operator_name=self.name,
149
+ strict=strict,
150
+ )
151
+
152
+ # Optional metrics collection (capture state after and compute)
153
+ if collect_metrics and state_before is not None:
154
+ metrics = self._collect_metrics(G, node, state_before)
155
+ # Store metrics in graph for retrieval
156
+ if "operator_metrics" not in G.graph:
157
+ G.graph["operator_metrics"] = []
158
+ G.graph["operator_metrics"].append(metrics)
159
+
160
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
161
+ """Validate operator-specific preconditions.
162
+
163
+ Override in subclasses to implement specific validation logic.
164
+ Base implementation does nothing.
165
+ """
166
+ pass
167
+
168
+ def _get_node_attr(self, G: TNFRGraph, node: Any, attr_name: str) -> float:
169
+ """Get node attribute value.
170
+
171
+ Parameters
172
+ ----------
173
+ G : TNFRGraph
174
+ Graph containing the node
175
+ node : Any
176
+ Node identifier
177
+ attr_name : str
178
+ Attribute name ("epi", "vf", "dnfr", "theta")
179
+
180
+ Returns
181
+ -------
182
+ float
183
+ Attribute value
184
+ """
185
+ from ..alias import get_attr
186
+ from ..constants.aliases import ALIAS_DNFR, ALIAS_EPI, ALIAS_THETA, ALIAS_VF
187
+
188
+ alias_map = {
189
+ "epi": ALIAS_EPI,
190
+ "vf": ALIAS_VF,
191
+ "dnfr": ALIAS_DNFR,
192
+ "theta": ALIAS_THETA,
193
+ }
194
+
195
+ aliases = alias_map.get(attr_name, (attr_name,))
196
+ return float(get_attr(G.nodes[node], aliases, 0.0))
197
+
198
+ def _capture_state(self, G: TNFRGraph, node: Any) -> dict[str, Any]:
199
+ """Capture node state before operator application.
200
+
201
+ Returns dict with relevant state for metrics computation.
202
+ """
203
+ from ..alias import get_attr
204
+ from ..constants.aliases import ALIAS_DNFR, ALIAS_EPI, ALIAS_THETA, ALIAS_VF
205
+
206
+ return {
207
+ "epi": float(get_attr(G.nodes[node], ALIAS_EPI, 0.0)),
208
+ "vf": float(get_attr(G.nodes[node], ALIAS_VF, 0.0)),
209
+ "dnfr": float(get_attr(G.nodes[node], ALIAS_DNFR, 0.0)),
210
+ "theta": float(get_attr(G.nodes[node], ALIAS_THETA, 0.0)),
211
+ }
212
+
213
+ def _collect_metrics(
214
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
215
+ ) -> dict[str, Any]:
216
+ """Collect operator-specific metrics.
217
+
218
+ Override in subclasses to implement specific metrics.
219
+ Base implementation returns basic state change.
220
+ """
221
+ from ..alias import get_attr
222
+ from ..constants.aliases import ALIAS_DNFR, ALIAS_EPI, ALIAS_THETA, ALIAS_VF
223
+
224
+ # Safely access glyph value
225
+ glyph_value = None
226
+ if self.glyph is not None:
227
+ glyph_value = (
228
+ self.glyph.value if hasattr(self.glyph, "value") else str(self.glyph)
229
+ )
230
+
231
+ return {
232
+ "operator": self.name,
233
+ "glyph": glyph_value,
234
+ "delta_epi": float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
235
+ - state_before["epi"],
236
+ "delta_vf": float(get_attr(G.nodes[node], ALIAS_VF, 0.0))
237
+ - state_before["vf"],
238
+ "delta_dnfr": float(get_attr(G.nodes[node], ALIAS_DNFR, 0.0))
239
+ - state_before["dnfr"],
240
+ "delta_theta": float(get_attr(G.nodes[node], ALIAS_THETA, 0.0))
241
+ - state_before["theta"],
242
+ }
243
+
244
+
245
+ @register_operator
246
+ class Emission(Operator):
247
+ """Emission structural operator (AL) - Foundational activation of nodal resonance.
248
+
249
+ Activates structural symbol ``AL`` to initialise outward resonance around a
250
+ nascent node, initiating the first phase of structural reorganization.
251
+
252
+ TNFR Context
253
+ ------------
254
+ In the Resonant Fractal Nature paradigm, Emission (AL) represents the moment when
255
+ a latent Primary Information Structure (EPI) begins to emit coherence toward its
256
+ surrounding network. This is not passive information broadcast but active structural
257
+ reorganization that increases the node's νf (structural frequency) and initiates
258
+ positive ΔNFR flow.
259
+
260
+ **Key Elements:**
261
+ - **Coherent Emergence**: Node exists because it resonates; AL initiates resonance
262
+ - **Structural Frequency**: Activates νf (Hz_str) to enable reorganization
263
+ - **Network Coupling**: Prepares node for phase alignment
264
+ - **Nodal Equation**: Implements ∂EPI/∂t = νf · ΔNFR(t) with positive ΔNFR
265
+
266
+ **Structural Irreversibility (TNFR.pdf §2.2.1):**
267
+ AL is inherently irreversible - once activated, it leaves a persistent structural
268
+ trace that cannot be undone. Each emission marks "time zero" for the node and
269
+ establishes genealogical traceability:
270
+
271
+ - **emission_timestamp**: ISO 8601 UTC timestamp of first activation
272
+ - **_emission_activated**: Immutable boolean flag
273
+ - **_emission_origin**: Preserved original timestamp (never overwritten)
274
+ - **_structural_lineage**: Genealogical record with:
275
+ - ``origin``: First emission timestamp
276
+ - ``activation_count``: Number of AL applications
277
+ - ``derived_nodes``: List for tracking EPI emergence (future use)
278
+ - ``parent_emission``: Reference to parent node (future use)
279
+
280
+ Re-activation increments ``activation_count`` while preserving original timestamp.
281
+
282
+ Use Cases
283
+ ---------
284
+ **Biomedical**: HRV coherence training, neural activation, therapeutic initiation
285
+ **Cognitive**: Idea germination, learning initiation, creative spark
286
+ **Social**: Team activation, community emergence, ritual initiation
287
+
288
+ Typical Sequences
289
+ -----------------
290
+ **AL → EN → IL → SHA**: Basic activation with stabilization and silence
291
+ **AL → RA**: Emission with immediate propagation
292
+ **AL → NAV → IL**: Phased activation with transition
293
+
294
+ Preconditions
295
+ -------------
296
+ - EPI < 0.8 (activation threshold)
297
+ - Node in latent or low-activation state
298
+ - Sufficient network coupling potential
299
+
300
+ Structural Effects
301
+ ------------------
302
+ **EPI**: Increments (form activation)
303
+ **νf**: Activates/increases (Hz_str)
304
+ **ΔNFR**: Initializes positive reorganization
305
+ **θ**: Influences phase alignment
306
+
307
+ Examples
308
+ --------
309
+ >>> from tnfr.constants import DNFR_PRIMARY, EPI_PRIMARY, VF_PRIMARY
310
+ >>> from tnfr.dynamics import set_delta_nfr_hook
311
+ >>> from tnfr.structural import create_nfr, run_sequence
312
+ >>> from tnfr.operators.definitions import Emission, Reception, Coherence, Silence
313
+ >>> G, node = create_nfr("seed", epi=0.18, vf=1.0)
314
+ >>> run_sequence(G, node, [Emission(), Reception(), Coherence(), Silence()])
315
+ >>> # Verify irreversibility
316
+ >>> assert G.nodes[node]["_emission_activated"] is True
317
+ >>> assert "emission_timestamp" in G.nodes[node]
318
+ >>> print(f"Activated at: {G.nodes[node]['emission_timestamp']}") # doctest: +SKIP
319
+ Activated at: 2025-11-07T15:47:10.209731+00:00
320
+
321
+ See Also
322
+ --------
323
+ Coherence : Stabilizes emitted structures
324
+ Resonance : Propagates emitted coherence
325
+ Reception : Receives external emissions
326
+ """
327
+
328
+ __slots__ = ()
329
+ name: ClassVar[str] = EMISSION
330
+ glyph: ClassVar[Glyph] = Glyph.AL
331
+
332
+ def __call__(self, G: TNFRGraph, node: Any, **kw: Any) -> None:
333
+ """Apply AL with structural irreversibility tracking.
334
+
335
+ Marks temporal irreversibility before delegating to grammar execution.
336
+ This ensures every emission leaves a persistent structural trace as
337
+ required by TNFR.pdf §2.2.1 (AL - Foundational emission).
338
+
339
+ Parameters
340
+ ----------
341
+ G : TNFRGraph
342
+ Graph storing TNFR nodes and structural operator history.
343
+ node : Any
344
+ Identifier or object representing the target node within ``G``.
345
+ **kw : Any
346
+ Additional keyword arguments forwarded to the grammar layer.
347
+ """
348
+ # Check and clear latency state if reactivating from silence
349
+ self._check_reactivation(G, node)
350
+
351
+ # Mark structural irreversibility BEFORE grammar execution
352
+ self._mark_irreversibility(G, node)
353
+
354
+ # Delegate to parent __call__ which applies grammar
355
+ super().__call__(G, node, **kw)
356
+
357
+ def _check_reactivation(self, G: TNFRGraph, node: Any) -> None:
358
+ """Check and clear latency state when reactivating from silence.
359
+
360
+ When AL (Emission) is applied to a node in latent state (from SHA),
361
+ this validates the reactivation and clears the latency attributes.
362
+
363
+ Parameters
364
+ ----------
365
+ G : TNFRGraph
366
+ Graph containing the node.
367
+ node : Any
368
+ Target node being reactivated.
369
+
370
+ Warnings
371
+ --------
372
+ - Warns if node is being reactivated after extended silence (duration check)
373
+ - Warns if EPI has drifted from preserved value during silence
374
+ """
375
+ if G.nodes[node].get("latent", False):
376
+ # Node is in latent state, reactivating from silence
377
+ silence_duration = G.nodes[node].get("silence_duration", 0.0)
378
+
379
+ # Get max silence duration threshold from graph config
380
+ max_silence = G.graph.get("MAX_SILENCE_DURATION", float("inf"))
381
+
382
+ # Validate reactivation timing
383
+ if silence_duration > max_silence:
384
+ warnings.warn(
385
+ f"Node {node} reactivating after extended silence "
386
+ f"(duration: {silence_duration:.2f}, max: {max_silence:.2f})",
387
+ stacklevel=3,
388
+ )
389
+
390
+ # Check EPI preservation integrity
391
+ preserved_epi = G.nodes[node].get("preserved_epi")
392
+ if preserved_epi is not None:
393
+ from ..alias import get_attr
394
+
395
+ current_epi = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
396
+ epi_drift = abs(current_epi - preserved_epi)
397
+
398
+ # Allow small numerical drift (1% tolerance)
399
+ if epi_drift > 0.01 * abs(preserved_epi):
400
+ warnings.warn(
401
+ f"Node {node} EPI drifted during silence "
402
+ f"(preserved: {preserved_epi:.3f}, current: {current_epi:.3f}, "
403
+ f"drift: {epi_drift:.3f})",
404
+ stacklevel=3,
405
+ )
406
+
407
+ # Clear latency state
408
+ del G.nodes[node]["latent"]
409
+ if "latency_start_time" in G.nodes[node]:
410
+ del G.nodes[node]["latency_start_time"]
411
+ if "preserved_epi" in G.nodes[node]:
412
+ del G.nodes[node]["preserved_epi"]
413
+ if "silence_duration" in G.nodes[node]:
414
+ del G.nodes[node]["silence_duration"]
415
+
416
+ def _mark_irreversibility(self, G: TNFRGraph, node: Any) -> None:
417
+ """Mark structural irreversibility for AL operator.
418
+
419
+ According to TNFR.pdf §2.2.1, AL (Emission) is structurally irreversible:
420
+ "Una vez activado, AL reorganiza el campo. No puede deshacerse."
421
+
422
+ This method establishes:
423
+ - Temporal marker: ISO timestamp of first emission
424
+ - Activation flag: Persistent boolean indicating AL was activated
425
+ - Structural lineage: Genealogical record for EPI traceability
426
+
427
+ Parameters
428
+ ----------
429
+ G : TNFRGraph
430
+ Graph containing the node.
431
+ node : Any
432
+ Target node for emission marking.
433
+
434
+ Notes
435
+ -----
436
+ On first activation:
437
+ - Sets emission_timestamp (ISO format)
438
+ - Sets _emission_activated = True (immutable)
439
+ - Sets _emission_origin (timestamp copy for preservation)
440
+ - Initializes _structural_lineage dict
441
+
442
+ On re-activation:
443
+ - Preserves original timestamp
444
+ - Increments activation_count in lineage
445
+ """
446
+ from datetime import datetime, timezone
447
+
448
+ from ..alias import set_attr_str
449
+ from ..constants.aliases import ALIAS_EMISSION_TIMESTAMP
450
+
451
+ # Check if this is first activation
452
+ if "_emission_activated" not in G.nodes[node]:
453
+ # Generate UTC timestamp in ISO format
454
+ emission_timestamp = datetime.now(timezone.utc).isoformat()
455
+
456
+ # Set canonical timestamp using alias system (use set_attr_str for string values)
457
+ set_attr_str(G.nodes[node], ALIAS_EMISSION_TIMESTAMP, emission_timestamp)
458
+
459
+ # Set persistent activation flag (immutable marker)
460
+ G.nodes[node]["_emission_activated"] = True
461
+
462
+ # Preserve origin timestamp (never overwritten)
463
+ G.nodes[node]["_emission_origin"] = emission_timestamp
464
+
465
+ # Initialize structural lineage for genealogical traceability
466
+ G.nodes[node]["_structural_lineage"] = {
467
+ "origin": emission_timestamp,
468
+ "activation_count": 1,
469
+ "derived_nodes": [], # Nodes that emerge from this emission
470
+ "parent_emission": None, # If derived from another node
471
+ }
472
+ else:
473
+ # Re-activation case: increment counter, preserve original timestamp
474
+ if "_structural_lineage" in G.nodes[node]:
475
+ G.nodes[node]["_structural_lineage"]["activation_count"] += 1
476
+
477
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
478
+ """Validate AL-specific preconditions with strict canonical checks.
479
+
480
+ Implements TNFR.pdf §2.2.1 precondition validation:
481
+ 1. EPI < latent threshold (node in nascent/latent state)
482
+ 2. νf > basal threshold (sufficient structural frequency)
483
+ 3. Network connectivity check (warning for isolated nodes)
484
+
485
+ Raises
486
+ ------
487
+ ValueError
488
+ If EPI too high or νf too low for emission
489
+ """
490
+ from .preconditions.emission import validate_emission_strict
491
+
492
+ validate_emission_strict(G, node)
493
+
494
+ def _collect_metrics(
495
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
496
+ ) -> dict[str, Any]:
497
+ """Collect AL-specific metrics."""
498
+ from .metrics import emission_metrics
499
+
500
+ return emission_metrics(G, node, state_before["epi"], state_before["vf"])
501
+
502
+
503
+ @register_operator
504
+ class Reception(Operator):
505
+ """Reception structural operator (EN) - Anchoring external coherence into local structure.
506
+
507
+ Activates structural symbol ``EN`` to anchor external coherence into the node's EPI,
508
+ stabilizing inbound information flows and integrating network resonance.
509
+
510
+ TNFR Context
511
+ ------------
512
+ Reception (EN) represents the structural capacity to receive and integrate coherence
513
+ from the network into the node's local EPI. Unlike passive data reception, EN is an
514
+ active structural process that reorganizes the node to accommodate and stabilize
515
+ external resonant patterns while reducing ΔNFR through integration.
516
+
517
+ **Key Elements:**
518
+
519
+ - **Active Integration**: Receiving is reorganizing, not passive storage
520
+ - **ΔNFR Reduction**: Integration reduces reorganization pressure
521
+ - **Network Coupling**: Requires phase compatibility with emitting nodes
522
+ - **Coherence Preservation**: External patterns maintain their structural identity
523
+
524
+ Use Cases
525
+ ---------
526
+ **Biomedical**:
527
+
528
+ - **Biofeedback Reception**: Integrating external coherence signals (e.g., HRV monitoring)
529
+ - **Therapeutic Resonance**: Patient receiving therapist's coherent presence
530
+ - **Neural Synchronization**: Brain regions receiving and integrating signals
531
+
532
+ **Cognitive**:
533
+
534
+ - **Learning Reception**: Student integrating teacher's explanations
535
+ - **Concept Integration**: Mind receiving and structuring new information
536
+ - **Attention Anchoring**: Consciousness stabilizing around received stimuli
537
+
538
+ **Social**:
539
+
540
+ - **Communication Reception**: Team member integrating collaborative input
541
+ - **Cultural Integration**: Individual receiving and adopting social patterns
542
+ - **Empathic Reception**: Receiving and resonating with others' emotional states
543
+
544
+ Typical Sequences
545
+ ---------------------------
546
+ - **AL → EN**: Emission followed by reception (bidirectional activation)
547
+ - **EN → IL**: Reception followed by coherence (stabilized integration)
548
+ - **RA → EN**: Resonance propagation followed by reception (network flow)
549
+ - **EN → THOL**: Reception triggering self-organization (emergent integration)
550
+ - **EN → UM**: Reception enabling coupling (synchronized reception)
551
+
552
+ Preconditions
553
+ -------------
554
+ - Node must have receptive capacity (non-saturated EPI)
555
+ - External coherence sources must be present in network
556
+ - Phase compatibility with emitting nodes
557
+
558
+ Structural Effects
559
+ ------------------
560
+ - **EPI**: Increments through integration of external patterns
561
+ - **ΔNFR**: Typically reduces as external coherence stabilizes node
562
+ - **θ**: May align toward emitting nodes' phase
563
+ - **Network coupling**: Strengthens connections to coherence sources
564
+
565
+ Metrics
566
+ -----------------
567
+ - ΔEPI: Magnitude of integrated external coherence
568
+ - ΔNFR reduction: Measure of stabilization effectiveness
569
+ - Integration efficiency: Ratio of received to integrated coherence
570
+ - Phase alignment: Degree of synchronization with sources
571
+
572
+ Compatibility
573
+ ---------------------
574
+ **Compatible with**: IL (Coherence), THOL (Self-organization), UM (Coupling),
575
+ RA (Resonance), NAV (Transition)
576
+
577
+ **Avoid with**: SHA (Silence) - contradicts receptive intent
578
+
579
+ **Natural progressions**: EN typically followed by stabilization (IL) or
580
+ organization (THOL) of received patterns
581
+
582
+ Examples
583
+ --------
584
+ **Technical Example:**
585
+
586
+ >>> from tnfr.constants import DNFR_PRIMARY, EPI_PRIMARY
587
+ >>> from tnfr.dynamics import set_delta_nfr_hook
588
+ >>> from tnfr.structural import create_nfr, run_sequence
589
+ >>> from tnfr.operators.definitions import Reception
590
+ >>> G, node = create_nfr("receiver", epi=0.30)
591
+ >>> G.nodes[node][DNFR_PRIMARY] = 0.12
592
+ >>> increments = iter([(0.05,)])
593
+ >>> def stabilise(graph):
594
+ ... (d_epi,) = next(increments)
595
+ ... graph.nodes[node][EPI_PRIMARY] += d_epi
596
+ ... graph.nodes[node][DNFR_PRIMARY] *= 0.5
597
+ >>> set_delta_nfr_hook(G, stabilise)
598
+ >>> run_sequence(G, node, [Reception()])
599
+ >>> round(G.nodes[node][EPI_PRIMARY], 2)
600
+ 0.35
601
+ >>> round(G.nodes[node][DNFR_PRIMARY], 2)
602
+ 0.06
603
+
604
+ **Example (Biofeedback Integration):**
605
+
606
+ >>> # Patient receiving HRV biofeedback during therapy
607
+ >>> G_patient, patient = create_nfr("patient_biofeedback", epi=0.30, vf=1.0)
608
+ >>> # EN: Patient's nervous system integrates coherence feedback
609
+ >>> run_sequence(G_patient, patient, [Reception()])
610
+ >>> # Result: External biofeedback signal anchors into patient's physiology
611
+ >>> # ΔNFR reduces as system stabilizes around received pattern
612
+
613
+ **Example (Educational Integration):**
614
+
615
+ >>> # Student receiving and integrating new mathematical concept
616
+ >>> G_learning, learner = create_nfr("student_mind", epi=0.25, vf=0.95)
617
+ >>> # EN: Student's cognitive structure receives teacher's explanation
618
+ >>> run_sequence(G_learning, learner, [Reception()])
619
+ >>> # Result: New information integrates into existing knowledge structure
620
+ >>> # Mental EPI reorganizes to accommodate new concept
621
+
622
+ See Also
623
+ --------
624
+ Emission : Initiates patterns that EN can receive
625
+ Coherence : Stabilizes received patterns
626
+ SelfOrganization : Organizes received information
627
+ """
628
+
629
+ __slots__ = ()
630
+ name: ClassVar[str] = RECEPTION
631
+ glyph: ClassVar[Glyph] = Glyph.EN
632
+
633
+ def __call__(self, G: TNFRGraph, node: Any, **kw: Any) -> None:
634
+ """Apply EN with source detection and integration tracking.
635
+
636
+ Detects emission sources in the network BEFORE applying reception
637
+ grammar. This enables active reorganization from external sources
638
+ as specified in TNFR.pdf §2.2.1 (EN - Structural reception).
639
+
640
+ Parameters
641
+ ----------
642
+ G : TNFRGraph
643
+ Graph storing TNFR nodes and structural operator history.
644
+ node : Any
645
+ Identifier or object representing the target node within ``G``.
646
+ **kw : Any
647
+ Additional keyword arguments:
648
+ - track_sources (bool): Enable source detection (default: True).
649
+ When enabled, automatically detects emission sources before
650
+ grammar execution. This is a non-breaking enhancement - existing
651
+ code continues to work, with source detection adding observability
652
+ without changing operational semantics.
653
+ - max_distance (int): Maximum network distance for source search (default: 2)
654
+ - Other args forwarded to grammar layer
655
+
656
+ Notes
657
+ -----
658
+ **Source Detection Behavior (New in This Release)**:
659
+
660
+ By default, source detection is enabled (``track_sources=True``). This
661
+ is a non-breaking change because:
662
+
663
+ 1. Detection happens BEFORE grammar execution (no operational changes)
664
+ 2. Only adds metadata to nodes (``_reception_sources``)
665
+ 3. Warnings are informational, not errors
666
+ 4. Can be disabled with ``track_sources=False``
667
+
668
+ Existing code will see warnings if nodes have no emission sources,
669
+ which is informational and helps identify network topology issues.
670
+ To suppress warnings in isolated-node scenarios, set ``track_sources=False``.
671
+ """
672
+ # Detect emission sources BEFORE applying reception
673
+ if kw.get("track_sources", True):
674
+ from .network_analysis.source_detection import detect_emission_sources
675
+
676
+ max_distance = kw.get("max_distance", 2)
677
+ sources = detect_emission_sources(G, node, max_distance=max_distance)
678
+
679
+ # Store detected sources in node metadata for metrics and analysis
680
+ G.nodes[node]["_reception_sources"] = sources
681
+
682
+ # Warn if no compatible sources found
683
+ if not sources:
684
+ warnings.warn(
685
+ f"EN warning: Node '{node}' has no detectable emission sources. "
686
+ f"Reception may not integrate external coherence effectively.",
687
+ stacklevel=2,
688
+ )
689
+
690
+ # Delegate to parent __call__ which applies grammar
691
+ super().__call__(G, node, **kw)
692
+
693
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
694
+ """Validate EN-specific preconditions with strict canonical checks.
695
+
696
+ Implements TNFR.pdf §2.2.1 precondition validation:
697
+ 1. EPI < saturation threshold (receptive capacity available)
698
+ 2. DNFR < threshold (minimal dissonance for stable integration)
699
+ 3. Emission sources check (warning for isolated nodes)
700
+
701
+ Raises
702
+ ------
703
+ ValueError
704
+ If EPI too high or DNFR too high for reception
705
+ """
706
+ from .preconditions.reception import validate_reception_strict
707
+
708
+ validate_reception_strict(G, node)
709
+
710
+ def _collect_metrics(
711
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
712
+ ) -> dict[str, Any]:
713
+ """Collect EN-specific metrics."""
714
+ from .metrics import reception_metrics
715
+
716
+ return reception_metrics(G, node, state_before["epi"])
717
+
718
+
719
+ @register_operator
720
+ class Coherence(Operator):
721
+ """Coherence structural operator - Stabilization of structural alignment.
722
+
723
+ Activates the Coherence operator to compress ΔNFR drift and raise the local C(t),
724
+ reinforcing structural alignment across nodes and stabilizing emergent forms.
725
+
726
+ TNFR Context
727
+ ------------
728
+ Coherence represents the fundamental stabilization process in TNFR. When applied,
729
+ it reduces ΔNFR (reorganization pressure) and increases C(t) (global coherence),
730
+ effectively "sealing" structural forms into stable configurations. This is the primary
731
+ operator for maintaining nodal equation balance: ∂EPI/∂t → 0 as ΔNFR → 0.
732
+
733
+ **Key Elements:**
734
+
735
+ - **Structural Stabilization**: Reduces reorganization pressure (ΔNFR)
736
+ - **Coherence Amplification**: Increases global C(t) through local stability
737
+ - **Form Preservation**: Maintains EPI integrity across time
738
+ - **Phase Locking**: Synchronizes node with network phase structure
739
+
740
+ Use Cases
741
+ ---------
742
+ **Biomedical**:
743
+
744
+ - **Cardiac Coherence**: Stabilizing heart rate variability patterns
745
+ - **Neural Coherence**: Maintaining synchronized brain wave states
746
+ - **Homeostatic Balance**: Stabilizing physiological regulatory systems
747
+ - **Therapeutic Integration**: Consolidating healing states post-intervention
748
+
749
+ **Cognitive**:
750
+
751
+ - **Concept Consolidation**: Stabilizing newly learned information
752
+ - **Mental Clarity**: Reducing cognitive noise and confusion
753
+ - **Focus Maintenance**: Sustaining attention on coherent thought patterns
754
+ - **Memory Formation**: Consolidating experience into stable memories
755
+
756
+ **Social**:
757
+
758
+ - **Team Alignment**: Stabilizing collaborative working patterns
759
+ - **Cultural Coherence**: Maintaining shared values and practices
760
+ - **Ritual Completion**: Sealing ceremonial transformations
761
+ - **Group Synchrony**: Stabilizing collective resonance states
762
+
763
+ Typical Sequences
764
+ ---------------------------
765
+ - **Emission → Reception → Coherence**: Safe activation with stabilization
766
+ - **Reception → Coherence**: Integrated reception consolidated
767
+ - **Coherence → Mutation**: Coherence enabling controlled mutation (stable transformation)
768
+ - **Resonance → Coherence**: Resonance followed by stabilization (propagation consolidation)
769
+ - **Coupling → Coherence**: Network coupling stabilized into coherent form
770
+
771
+ Preconditions
772
+ -------------
773
+ - Node must have active EPI (non-zero form)
774
+ - ΔNFR should be present (though Coherence reduces it)
775
+ - Sufficient network coupling for phase alignment
776
+
777
+ Structural Effects
778
+ ------------------
779
+ - **EPI**: May increment slightly as form stabilizes
780
+ - **ΔNFR**: Significantly reduces (primary effect)
781
+ - **C(t)**: Increases at both local and global levels
782
+ - **νf**: May slightly increase as stability enables higher frequency
783
+ - **θ**: Aligns with network phase (phase locking)
784
+
785
+ Metrics
786
+ -----------------
787
+ - ΔNFR reduction: Primary metric of stabilization success
788
+ - C(t) increase: Global coherence improvement
789
+ - Phase alignment: Degree of network synchronization
790
+ - EPI stability: Variance reduction in form over time
791
+
792
+ Compatibility
793
+ ---------------------
794
+ **Compatible with**: ALL operators - Coherence is universally stabilizing
795
+
796
+ **Especially effective after**: Emission, Reception, Dissonance, Transition
797
+
798
+ **Natural progressions**: Coherence often concludes sequences or prepares for
799
+ controlled transformation (Mutation, Transition)
800
+
801
+ Examples
802
+ --------
803
+ **Cardiac Coherence Training:**
804
+
805
+ >>> from tnfr.structural import create_nfr, run_sequence
806
+ >>> from tnfr.operators.definitions import Emission, Reception, Coherence, Coupling, Resonance, Transition
807
+ >>> from tnfr.alias import get_attr
808
+ >>> from tnfr.constants.aliases import ALIAS_EPI
809
+ >>>
810
+ >>> # Stabilizing heart rhythm during breath-focus training
811
+ >>> G_heart, heart = create_nfr("cardiac_rhythm", epi=0.40, vf=1.10)
812
+ >>>
813
+ >>> # Valid sequence: Emission → Reception → Coherence → Coupling → Resonance → Transition
814
+ >>> run_sequence(G_heart, heart,
815
+ ... [Emission(), Reception(), Coherence(), Coupling(), Resonance(), Transition()])
816
+ >>>
817
+ >>> # Result: HRV pattern stabilizes, ΔNFR reduces
818
+ >>> epi_final = float(get_attr(G_heart.nodes[heart], ALIAS_EPI, 0.0))
819
+ >>> # Patient enters sustained coherent state
820
+
821
+ **Learning Consolidation:**
822
+
823
+ >>> # Student consolidating newly understood concept
824
+ >>> G_study, mind = create_nfr("student_understanding", epi=0.30, vf=1.05)
825
+ >>>
826
+ >>> # Receive teaching and consolidate understanding
827
+ >>> run_sequence(G_study, mind,
828
+ ... [Emission(), Reception(), Coherence(), Coupling(), Resonance(), Transition()])
829
+ >>>
830
+ >>> # Result: Knowledge structure stabilizes, confusion reduces
831
+ >>> # Concept becomes part of stable mental model
832
+
833
+ **Team Alignment:**
834
+
835
+ >>> # Collaborative team stabilizing after creative session
836
+ >>> G_team, group = create_nfr("team_consensus", epi=0.55, vf=1.00)
837
+ >>>
838
+ >>> # Build consensus through coupling and coherence
839
+ >>> run_sequence(G_team, group,
840
+ ... [Emission(), Reception(), Coupling(), Coherence(), Resonance(), Transition()])
841
+ >>>
842
+ >>> # Result: Group coherence increases, conflicts resolve
843
+ >>> # Team operates with unified purpose
844
+
845
+ See Also
846
+ --------
847
+ Dissonance : Creates instability that Coherence later resolves
848
+ Emission : Often followed by Coherence for safe activation
849
+ Mutation : Coherence enables controlled phase changes
850
+ """
851
+
852
+ __slots__ = ()
853
+ name: ClassVar[str] = COHERENCE
854
+ glyph: ClassVar[Glyph] = Glyph.IL
855
+
856
+ def __call__(self, G: TNFRGraph, node: Any, **kw: Any) -> None:
857
+ """Apply Coherence with explicit ΔNFR reduction, C(t) coherence tracking, and phase locking.
858
+
859
+ Parameters
860
+ ----------
861
+ G : TNFRGraph
862
+ Graph storing TNFR nodes and structural operator history.
863
+ node : Any
864
+ Identifier or object representing the target node within ``G``.
865
+ **kw : Any
866
+ Additional keyword arguments forwarded to grammar layer via parent __call__.
867
+ Special keys:
868
+ - coherence_radius (int): Radius for local coherence computation (default: 1)
869
+ - phase_locking_coefficient (float): Phase alignment strength α ∈ [0.1, 0.5] (default: 0.3)
870
+
871
+ Notes
872
+ -----
873
+ This implementation enforces the canonical Coherence structural effect:
874
+ ΔNFR → ΔNFR * (1 - ρ) where ρ ≈ 0.3 (30% reduction).
875
+
876
+ The reduction is applied by the grammar layer using the Coherence dnfr_factor
877
+ from global glyph factors. This method adds explicit telemetry logging for
878
+ structural traceability.
879
+
880
+ **C(t) Coherence Tracking:**
881
+
882
+ Captures global and local coherence before and after Coherence application:
883
+ - C_global: Network-wide coherence using C(t) = 1 - (σ_ΔNFR / ΔNFR_max)
884
+ - C_local: Node neighborhood coherence with configurable radius
885
+
886
+ Both metrics are stored in G.graph["IL_coherence_tracking"] for analysis.
887
+
888
+ **Phase Locking:**
889
+
890
+ Aligns node phase θ with network neighborhood phase:
891
+ - θ_node → θ_node + α * (θ_network - θ_node)
892
+ - Uses circular mean for proper phase wrap-around handling
893
+ - Telemetry stored in G.graph["IL_phase_locking"]
894
+
895
+ To customize the reduction factor, set GLYPH_FACTORS["IL_dnfr_factor"] in
896
+ the graph before calling this operator. Default is 0.7 (30% reduction).
897
+ """
898
+ # Import here to avoid circular import
899
+ from ..metrics.coherence import (
900
+ compute_global_coherence,
901
+ compute_local_coherence,
902
+ )
903
+
904
+ # Capture C(t) before Coherence application
905
+ C_global_before = compute_global_coherence(G)
906
+ C_local_before = compute_local_coherence(
907
+ G, node, radius=kw.get("coherence_radius", 1)
908
+ )
909
+
910
+ # Capture ΔNFR before Coherence application for telemetry
911
+ dnfr_before = float(get_attr(G.nodes[node], ALIAS_DNFR, 0.0))
912
+
913
+ # Delegate to parent __call__ which applies grammar (including Coherence reduction)
914
+ super().__call__(G, node, **kw)
915
+
916
+ # Apply phase locking after grammar application
917
+ locking_coef = kw.get("phase_locking_coefficient", 0.3)
918
+ self._apply_phase_locking(G, node, locking_coefficient=locking_coef)
919
+
920
+ # Capture C(t) after IL application
921
+ C_global_after = compute_global_coherence(G)
922
+ C_local_after = compute_local_coherence(
923
+ G, node, radius=kw.get("coherence_radius", 1)
924
+ )
925
+
926
+ # Capture ΔNFR after IL application for telemetry
927
+ dnfr_after = float(get_attr(G.nodes[node], ALIAS_DNFR, 0.0))
928
+
929
+ # Store C(t) tracking in graph telemetry
930
+ if "IL_coherence_tracking" not in G.graph:
931
+ G.graph["IL_coherence_tracking"] = []
932
+
933
+ G.graph["IL_coherence_tracking"].append(
934
+ {
935
+ "node": node,
936
+ "C_global_before": C_global_before,
937
+ "C_global_after": C_global_after,
938
+ "C_global_delta": C_global_after - C_global_before,
939
+ "C_local_before": C_local_before,
940
+ "C_local_after": C_local_after,
941
+ "C_local_delta": C_local_after - C_local_before,
942
+ }
943
+ )
944
+
945
+ # Log ΔNFR reduction in graph metadata for telemetry
946
+ if "IL_dnfr_reductions" not in G.graph:
947
+ G.graph["IL_dnfr_reductions"] = []
948
+
949
+ # Calculate actual reduction factor from before/after values
950
+ actual_reduction_factor = (
951
+ (dnfr_before - dnfr_after) / dnfr_before if dnfr_before > 0 else 0.0
952
+ )
953
+
954
+ G.graph["IL_dnfr_reductions"].append(
955
+ {
956
+ "node": node,
957
+ "before": dnfr_before,
958
+ "after": dnfr_after,
959
+ "reduction": dnfr_before - dnfr_after,
960
+ "reduction_factor": actual_reduction_factor,
961
+ }
962
+ )
963
+
964
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
965
+ """Validate IL-specific preconditions."""
966
+ from .preconditions import validate_coherence
967
+
968
+ validate_coherence(G, node)
969
+
970
+ def _collect_metrics(
971
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
972
+ ) -> dict[str, Any]:
973
+ """Collect IL-specific metrics."""
974
+ from .metrics import coherence_metrics
975
+
976
+ return coherence_metrics(G, node, state_before["dnfr"])
977
+
978
+ def _apply_phase_locking(
979
+ self, G: TNFRGraph, node: Any, locking_coefficient: float = 0.3
980
+ ) -> None:
981
+ """Align node phase θ with network neighborhood phase.
982
+
983
+ Implements canonical IL phase locking:
984
+ θ_node → θ_node + α * (θ_network - θ_node)
985
+
986
+ where α ∈ [0.1, 0.5] is the phase locking coefficient (default: 0.3).
987
+
988
+ Parameters
989
+ ----------
990
+ G : TNFRGraph
991
+ Network graph
992
+ node : Any
993
+ Target node
994
+ locking_coefficient : float
995
+ Phase alignment strength α, default 0.3
996
+
997
+ Notes
998
+ -----
999
+ **Canonical Specification:**
1000
+
1001
+ IL operator synchronizes node phase with its network neighborhood:
1002
+
1003
+ 1. Compute network phase θ_network as circular mean of neighbor phases
1004
+ 2. Compute phase difference Δθ = θ_network - θ_node (shortest arc)
1005
+ 3. Apply locking: θ_new = θ_node + α * Δθ
1006
+ 4. Normalize θ_new to [0, 2π]
1007
+
1008
+ **Circular Statistics:**
1009
+
1010
+ Phase averaging uses complex exponentials to handle wrap-around at 2π:
1011
+ - Convert phases to e^(iθ)
1012
+ - Compute mean of complex phasors
1013
+ - Extract angle as network phase
1014
+
1015
+ This ensures correct averaging (e.g., 0.1 and 6.2 radians average to ~0).
1016
+
1017
+ **Telemetry:**
1018
+
1019
+ Stores detailed phase locking information in G.graph["IL_phase_locking"]:
1020
+ - theta_before, theta_after: Node phase before/after locking
1021
+ - theta_network: Network neighborhood mean phase
1022
+ - delta_theta: Phase difference (shortest arc)
1023
+ - alignment_achieved: Residual misalignment after locking
1024
+
1025
+ **Special Cases:**
1026
+
1027
+ - No neighbors: Phase unchanged (no network to align with)
1028
+ - Single neighbor: Aligns toward that neighbor's phase
1029
+ - Isolated node: No-op (returns immediately)
1030
+
1031
+ See Also
1032
+ --------
1033
+ metrics.phase_coherence.compute_phase_alignment : Measure alignment quality
1034
+ """
1035
+ from ..alias import set_attr
1036
+ from ..constants.aliases import ALIAS_THETA
1037
+
1038
+ # Get current node phase
1039
+ theta_node = float(get_attr(G.nodes[node], ALIAS_THETA, 0.0))
1040
+
1041
+ # Get neighbor phases
1042
+ neighbors = list(G.neighbors(node))
1043
+ if not neighbors:
1044
+ return # No neighbors, no phase locking
1045
+
1046
+ theta_neighbors = [
1047
+ float(get_attr(G.nodes[n], ALIAS_THETA, 0.0)) for n in neighbors
1048
+ ]
1049
+
1050
+ # Compute mean phase using circular mean (angles wrap around 2π)
1051
+ # Convert to complex exponentials for circular averaging
1052
+ np = get_numpy()
1053
+
1054
+ if np is not None:
1055
+ # NumPy vectorized computation
1056
+ theta_array = np.array(theta_neighbors)
1057
+ complex_phases = np.exp(1j * theta_array)
1058
+ mean_complex = np.mean(complex_phases)
1059
+ theta_network = np.angle(mean_complex) # Returns value in [-π, π]
1060
+
1061
+ # Ensure positive phase [0, 2π]
1062
+ if theta_network < 0:
1063
+ theta_network = float(theta_network + 2 * np.pi)
1064
+ else:
1065
+ theta_network = float(theta_network)
1066
+
1067
+ # Compute phase difference (considering wrap-around)
1068
+ delta_theta = theta_network - theta_node
1069
+
1070
+ # Normalize to [-π, π] for shortest angular distance
1071
+ if delta_theta > np.pi:
1072
+ delta_theta -= 2 * np.pi
1073
+ elif delta_theta < -np.pi:
1074
+ delta_theta += 2 * np.pi
1075
+ delta_theta = float(delta_theta)
1076
+
1077
+ # Apply phase locking: move θ toward network mean
1078
+ theta_new = theta_node + locking_coefficient * delta_theta
1079
+
1080
+ # Normalize to [0, 2π]
1081
+ theta_new = float(theta_new % (2 * np.pi))
1082
+ import cmath
1083
+ import math
1084
+
1085
+ # Convert phases to complex exponentials
1086
+ complex_phases = [cmath.exp(1j * theta) for theta in theta_neighbors]
1087
+
1088
+ # Compute mean complex phasor
1089
+ mean_real = sum(z.real for z in complex_phases) / len(complex_phases)
1090
+ mean_imag = sum(z.imag for z in complex_phases) / len(complex_phases)
1091
+ mean_complex = complex(mean_real, mean_imag)
1092
+
1093
+ # Extract angle (in [-π, π])
1094
+ theta_network = cmath.phase(mean_complex)
1095
+
1096
+ # Ensure positive phase [0, 2π]
1097
+ if theta_network < 0:
1098
+ theta_network += 2 * math.pi
1099
+
1100
+ # Compute phase difference (considering wrap-around)
1101
+ delta_theta = theta_network - theta_node
1102
+
1103
+ # Normalize to [-π, π] for shortest angular distance
1104
+ if delta_theta > math.pi:
1105
+ delta_theta -= 2 * math.pi
1106
+ elif delta_theta < -math.pi:
1107
+ delta_theta += 2 * math.pi
1108
+
1109
+ # Apply phase locking: move θ toward network mean
1110
+ theta_new = theta_node + locking_coefficient * delta_theta
1111
+
1112
+ # Normalize to [0, 2π]
1113
+ theta_new = theta_new % (2 * math.pi)
1114
+
1115
+ # Update node phase
1116
+ set_attr(G.nodes[node], ALIAS_THETA, theta_new)
1117
+
1118
+ # Store phase locking telemetry
1119
+ if "IL_phase_locking" not in G.graph:
1120
+ G.graph["IL_phase_locking"] = []
1121
+
1122
+ G.graph["IL_phase_locking"].append(
1123
+ {
1124
+ "node": node,
1125
+ "theta_before": theta_node,
1126
+ "theta_after": theta_new,
1127
+ "theta_network": theta_network,
1128
+ "delta_theta": delta_theta,
1129
+ "alignment_achieved": abs(delta_theta) * (1 - locking_coefficient),
1130
+ }
1131
+ )
1132
+
1133
+
1134
+ @register_operator
1135
+ class Dissonance(Operator):
1136
+ """Dissonance structural operator (OZ) - Creative instability for exploration.
1137
+
1138
+ Activates structural symbol ``OZ`` to widen ΔNFR and test bifurcation thresholds,
1139
+ injecting controlled dissonance to probe system robustness and enable transformation.
1140
+
1141
+ TNFR Context
1142
+ ------------
1143
+ Dissonance (OZ) is the creative force in TNFR - it deliberately increases ΔNFR and
1144
+ phase instability (θ) to explore new structural configurations. Rather than destroying
1145
+ coherence, controlled dissonance enables evolution, mutation, and creative reorganization.
1146
+ When ∂²EPI/∂t² > τ, bifurcation occurs, spawning new structural possibilities.
1147
+
1148
+ **Key Elements:**
1149
+
1150
+ - **Creative Instability**: Necessary for transformation and evolution
1151
+ - **Bifurcation Trigger**: When ΔNFR exceeds thresholds, new forms emerge
1152
+ - **Controlled Chaos**: Dissonance is managed, not destructive
1153
+ - **Phase Exploration**: θ variation opens new network couplings
1154
+
1155
+ Use Cases
1156
+ ---------
1157
+ **Biomedical**:
1158
+
1159
+ - **Hormetic Stress**: Controlled physiological challenge (cold exposure, fasting)
1160
+ - **Therapeutic Crisis**: Necessary discomfort in healing process
1161
+ - **Immune Challenge**: Controlled pathogen exposure for adaptation
1162
+ - **Neural Plasticity**: Learning-induced temporary destabilization
1163
+
1164
+ **Cognitive**:
1165
+
1166
+ - **Cognitive Dissonance**: Challenging existing beliefs for growth
1167
+ - **Creative Problem-Solving**: Introducing paradoxes to spark insight
1168
+ - **Socratic Method**: Questioning to destabilize and rebuild understanding
1169
+ - **Conceptual Conflict**: Encountering contradictions that force reorganization
1170
+
1171
+ **Social**:
1172
+
1173
+ - **Constructive Conflict**: Productive disagreement in teams
1174
+ - **Organizational Change**: Disrupting status quo to enable transformation
1175
+ - **Cultural Evolution**: Introducing new ideas that challenge norms
1176
+ - **Innovation Pressure**: Market disruption forcing adaptation
1177
+
1178
+ Typical Sequences
1179
+ ---------------------------
1180
+ - **OZ → IL**: Dissonance resolved into new coherence (creative resolution)
1181
+ - **OZ → THOL**: Dissonance triggering self-organization (emergent order)
1182
+ - **IL → OZ → THOL**: Stable → dissonance → reorganization (growth cycle)
1183
+ - **OZ → NAV → IL**: Dissonance → transition → new stability
1184
+ - **AL → OZ → RA**: Activation → challenge → propagation (tested resonance)
1185
+
1186
+ **AVOID**: OZ → SHA (dissonance followed by silence contradicts exploration)
1187
+
1188
+ Preconditions
1189
+ -------------
1190
+ - Node must have baseline coherence to withstand dissonance
1191
+ - Network must support potential bifurcations
1192
+ - ΔNFR should not already be critically high
1193
+
1194
+ Structural Effects
1195
+ ------------------
1196
+ - **ΔNFR**: Significantly increases (primary effect)
1197
+ - **θ**: May shift unpredictably (phase exploration)
1198
+ - **EPI**: May temporarily destabilize before reorganizing
1199
+ - **νf**: Often increases as system responds to challenge
1200
+ - **Bifurcation risk**: ∂²EPI/∂t² may exceed τ
1201
+
1202
+ Metrics
1203
+ -----------------
1204
+ - ΔNFR increase: Magnitude of introduced instability
1205
+ - Phase shift (Δθ): Degree of phase exploration
1206
+ - Bifurcation events: Count of structural splits
1207
+ - Recovery time: Time to return to coherence (with IL)
1208
+
1209
+ Compatibility
1210
+ ---------------------
1211
+ **Compatible with**: IL (resolution), THOL (organization), NAV (transition),
1212
+ ZHIR (mutation)
1213
+
1214
+ **Avoid with**: SHA (silence), multiple consecutive OZ (excessive instability)
1215
+
1216
+ **Natural progressions**: OZ typically followed by IL (stabilization) or
1217
+ THOL (self-organization) to resolve created instability
1218
+
1219
+ Examples
1220
+ --------
1221
+ **Technical Example:**
1222
+
1223
+ >>> from tnfr.constants import DNFR_PRIMARY, THETA_PRIMARY
1224
+ >>> from tnfr.dynamics import set_delta_nfr_hook
1225
+ >>> from tnfr.structural import create_nfr, run_sequence
1226
+ >>> from tnfr.operators.definitions import Dissonance
1227
+ >>> G, node = create_nfr("probe", theta=0.10)
1228
+ >>> G.nodes[node][DNFR_PRIMARY] = 0.02
1229
+ >>> shocks = iter([(0.09, 0.15)])
1230
+ >>> def inject(graph):
1231
+ ... d_dnfr, d_theta = next(shocks)
1232
+ ... graph.nodes[node][DNFR_PRIMARY] += d_dnfr
1233
+ ... graph.nodes[node][THETA_PRIMARY] += d_theta
1234
+ >>> set_delta_nfr_hook(G, inject)
1235
+ >>> run_sequence(G, node, [Dissonance()])
1236
+ >>> round(G.nodes[node][DNFR_PRIMARY], 2)
1237
+ 0.11
1238
+ >>> round(G.nodes[node][THETA_PRIMARY], 2)
1239
+ 0.25
1240
+
1241
+ **Example (Therapeutic Challenge):**
1242
+
1243
+ >>> # Patient confronting difficult emotions in therapy
1244
+ >>> G_therapy, patient = create_nfr("emotional_processing", epi=0.40, theta=0.10)
1245
+ >>> # Stable baseline, low phase variation
1246
+ >>> # OZ: Therapist guides patient to face uncomfortable truth
1247
+ >>> run_sequence(G_therapy, patient, [Dissonance()])
1248
+ >>> # Result: ΔNFR increases (emotional turbulence)
1249
+ >>> # Phase shifts as old patterns destabilize
1250
+ >>> # Prepares for THOL (new understanding) or IL (integration)
1251
+
1252
+ **Example (Educational Challenge):**
1253
+
1254
+ >>> # Student encountering paradox that challenges understanding
1255
+ >>> G_learning, student = create_nfr("conceptual_framework", epi=0.50, theta=0.15)
1256
+ >>> # Established understanding with moderate phase stability
1257
+ >>> # OZ: Teacher presents evidence contradicting current model
1258
+ >>> run_sequence(G_learning, student, [Dissonance()])
1259
+ >>> # Result: Cognitive dissonance creates ΔNFR spike
1260
+ >>> # Existing mental model destabilizes
1261
+ >>> # Enables THOL (conceptual reorganization) or ZHIR (paradigm shift)
1262
+
1263
+ **Example (Organizational Innovation):**
1264
+
1265
+ >>> # Company facing market disruption
1266
+ >>> G_org, company = create_nfr("business_model", epi=0.60, theta=0.20)
1267
+ >>> # Established business model with some flexibility
1268
+ >>> # OZ: Disruptive competitor enters market
1269
+ >>> run_sequence(G_org, company, [Dissonance()])
1270
+ >>> # Result: Organizational ΔNFR increases (uncertainty, pressure)
1271
+ >>> # Business model phase shifts (exploring new strategies)
1272
+ >>> # Creates conditions for THOL (innovation) or NAV (pivot)
1273
+
1274
+ See Also
1275
+ --------
1276
+ Coherence : Resolves dissonance into new stability
1277
+ SelfOrganization : Organizes dissonance into emergent forms
1278
+ Mutation : Controlled phase change often enabled by OZ
1279
+ """
1280
+
1281
+ __slots__ = ()
1282
+ name: ClassVar[str] = DISSONANCE
1283
+ glyph: ClassVar[Glyph] = Glyph.OZ
1284
+
1285
+ def __call__(self, G: TNFRGraph, node: Any, **kw: Any) -> None:
1286
+ """Apply OZ with optional network propagation.
1287
+
1288
+ Parameters
1289
+ ----------
1290
+ G : TNFRGraph
1291
+ Graph storing TNFR nodes
1292
+ node : Any
1293
+ Target node identifier
1294
+ **kw : Any
1295
+ Additional keyword arguments:
1296
+ - propagate_to_network: Enable propagation (default: True if OZ_ENABLE_PROPAGATION in G.graph)
1297
+ - propagation_mode: 'phase_weighted' (default), 'uniform', 'frequency_weighted'
1298
+ - Other arguments forwarded to base Operator.__call__
1299
+ """
1300
+ # Capture state before for propagation computation
1301
+ dnfr_before = float(get_attr(G.nodes[node], ALIAS_DNFR, 0.0))
1302
+
1303
+ # Apply standard operator logic via parent
1304
+ super().__call__(G, node, **kw)
1305
+
1306
+ # Compute dissonance increase
1307
+ dnfr_after = float(get_attr(G.nodes[node], ALIAS_DNFR, 0.0))
1308
+ dissonance_magnitude = abs(dnfr_after - dnfr_before)
1309
+
1310
+ # Propagate to network if enabled
1311
+ propagate = kw.get(
1312
+ "propagate_to_network", G.graph.get("OZ_ENABLE_PROPAGATION", True)
1313
+ )
1314
+ if propagate and dissonance_magnitude > 0:
1315
+ from ..dynamics.propagation import propagate_dissonance
1316
+
1317
+ affected = propagate_dissonance(
1318
+ G,
1319
+ node,
1320
+ dissonance_magnitude,
1321
+ propagation_mode=kw.get("propagation_mode", "phase_weighted"),
1322
+ )
1323
+
1324
+ # Store propagation telemetry
1325
+ if "_oz_propagation_events" not in G.graph:
1326
+ G.graph["_oz_propagation_events"] = []
1327
+ G.graph["_oz_propagation_events"].append(
1328
+ {
1329
+ "source": node,
1330
+ "magnitude": dissonance_magnitude,
1331
+ "affected_nodes": list(affected),
1332
+ "affected_count": len(affected),
1333
+ }
1334
+ )
1335
+
1336
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
1337
+ """Validate OZ-specific preconditions."""
1338
+ from .preconditions import validate_dissonance
1339
+
1340
+ validate_dissonance(G, node)
1341
+
1342
+ def _collect_metrics(
1343
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
1344
+ ) -> dict[str, Any]:
1345
+ """Collect OZ-specific metrics."""
1346
+ from .metrics import dissonance_metrics
1347
+
1348
+ return dissonance_metrics(G, node, state_before["dnfr"], state_before["theta"])
1349
+
1350
+
1351
+ @register_operator
1352
+ class Coupling(Operator):
1353
+ """Coupling structural operator (UM) - Synchronization of nodal phases.
1354
+
1355
+ Activates glyph ``UM`` to stabilize bidirectional coherence links by synchronizing
1356
+ coupling phase and bandwidth between nodes.
1357
+
1358
+ TNFR Context
1359
+ ------------
1360
+ Coupling (UM) creates or strengthens structural connections between nodes through phase
1361
+ synchronization (φᵢ(t) ≈ φⱼ(t)). This is not mere correlation but active structural
1362
+ resonance that enables coordinated reorganization and shared coherence. Coupling is
1363
+ essential for network-level coherence and collective structural dynamics.
1364
+
1365
+ **Key Elements:**
1366
+
1367
+ - **Phase Synchronization**: Nodes align their θ values for resonance
1368
+ - **Bidirectional Flow**: Coupling enables mutual influence and coherence sharing
1369
+ - **Network Formation**: UM builds the relational structure of NFR networks
1370
+ - **Collective Coherence**: Multiple coupled nodes create emergent stability
1371
+
1372
+ Use Cases
1373
+ ---------
1374
+ **Biomedical**:
1375
+
1376
+ - **Heart-Brain Coupling**: Synchronizing cardiac and neural rhythms
1377
+ - **Respiratory-Cardiac Coherence**: Breath-heart rate variability coupling
1378
+ - **Interpersonal Synchrony**: Physiological attunement between people
1379
+ - **Neural Network Coupling**: Synchronized firing patterns across brain regions
1380
+
1381
+ **Cognitive**:
1382
+
1383
+ - **Conceptual Integration**: Linking related ideas into coherent frameworks
1384
+ - **Teacher-Student Attunement**: Pedagogical resonance and rapport
1385
+ - **Collaborative Thinking**: Shared mental models in teams
1386
+ - **Memory Association**: Coupling related memories for retrieval
1387
+
1388
+ **Social**:
1389
+
1390
+ - **Team Bonding**: Creating synchronized group dynamics
1391
+ - **Cultural Transmission**: Coupling individual to collective patterns
1392
+ - **Communication Channels**: Establishing mutual understanding
1393
+ - **Network Effects**: Value creation through connection density
1394
+
1395
+ Typical Sequences
1396
+ ---------------------------
1397
+ - **UM → RA**: Coupling followed by resonance propagation
1398
+ - **AL → UM**: Emission followed by coupling (paired activation)
1399
+ - **UM → IL**: Coupling stabilized into coherence
1400
+ - **EN → UM**: Reception enabling coupling (receptive connection)
1401
+ - **UM → THOL**: Coupling triggering collective self-organization
1402
+
1403
+ Preconditions
1404
+ -------------
1405
+ **Canonical Requirements (TNFR Theory)**:
1406
+
1407
+ 1. **Graph connectivity**: At least one other node exists for potential coupling
1408
+ 2. **Active EPI**: Node must have sufficient structural form (EPI > threshold)
1409
+ - Default threshold: 0.05 (configurable via ``UM_MIN_EPI``)
1410
+ - Ensures node has coherent structure capable of synchronization
1411
+ 3. **Structural frequency**: Node must have capacity for synchronization (νf > threshold)
1412
+ - Default threshold: 0.01 Hz_str (configurable via ``UM_MIN_VF``)
1413
+ - Ensures node can actively respond to coupling dynamics
1414
+ 4. **Phase compatibility** (optional): Compatible neighbors within phase range
1415
+ - Enabled via ``UM_STRICT_PHASE_CHECK`` flag (default: False)
1416
+ - Maximum phase difference: π/2 radians (configurable via ``UM_MAX_PHASE_DIFF``)
1417
+ - Soft check by default since UM can create new functional links
1418
+
1419
+ **Configuration Parameters**:
1420
+
1421
+ - ``UM_MIN_EPI`` (float, default 0.05): Minimum EPI magnitude for coupling
1422
+ - ``UM_MIN_VF`` (float, default 0.01): Minimum structural frequency for coupling
1423
+ - ``UM_STRICT_PHASE_CHECK`` (bool, default False): Enable phase compatibility checking
1424
+ - ``UM_MAX_PHASE_DIFF`` (float, default π/2): Maximum phase difference for compatibility
1425
+
1426
+ **Validation Control**:
1427
+
1428
+ Set ``VALIDATE_OPERATOR_PRECONDITIONS=True`` in graph metadata to enable validation.
1429
+ Validation is backward-compatible and disabled by default to preserve existing behavior.
1430
+
1431
+ Structural Invariants
1432
+ ---------------------
1433
+ **CRITICAL**: UM preserves EPI identity. The coupling process synchronizes
1434
+ phases (θ), may align structural frequencies (νf), and can reduce ΔNFR, but
1435
+ it NEVER directly modifies EPI. This ensures that coupled nodes maintain
1436
+ their structural identities while achieving phase coherence.
1437
+
1438
+ Any change to EPI during a sequence containing UM must come from other
1439
+ operators (e.g., Emission, Reception) or from the natural evolution via
1440
+ the nodal equation ∂EPI/∂t = νf · ΔNFR(t), never from UM itself.
1441
+
1442
+ **Theoretical Basis**: In TNFR theory, coupling (UM) creates structural links
1443
+ through phase synchronization φᵢ(t) ≈ φⱼ(t), not through information transfer
1444
+ or EPI modification. The structural identity (EPI) of each node remains intact
1445
+ while the nodes achieve synchronized phases that enable resonant interaction.
1446
+
1447
+ **Implementation Guarantee**: The `_op_UM` function modifies only:
1448
+
1449
+ - Phase (θ): Adjusted towards consensus phase
1450
+ - Structural frequency (νf): Optionally synchronized with neighbors
1451
+ - Reorganization gradient (ΔNFR): Reduced through stabilization
1452
+
1453
+ EPI is never touched by the coupling logic, preserving this fundamental invariant.
1454
+
1455
+ Structural Effects
1456
+ ------------------
1457
+ - **θ**: Phases of coupled nodes converge (primary effect)
1458
+ - **νf**: May synchronize between coupled nodes
1459
+ - **ΔNFR**: Often reduces through mutual stabilization
1460
+ - **Network structure**: Creates or strengthens edges
1461
+ - **Collective EPI**: Enables emergent shared structures
1462
+
1463
+ Metrics
1464
+ -----------------
1465
+ - Phase alignment: |θᵢ - θⱼ| reduction
1466
+ - Coupling strength: Magnitude of mutual influence
1467
+ - Network density: Number of active couplings
1468
+ - Collective coherence: C(t) at network level
1469
+
1470
+ Compatibility
1471
+ ---------------------
1472
+ **Compatible with**: RA (Resonance), IL (Coherence), THOL (Self-organization),
1473
+ EN (Reception), AL (Emission)
1474
+
1475
+ **Synergistic with**: RA (coupling + propagation = network coherence)
1476
+
1477
+ **Natural progressions**: UM often followed by RA (propagation through
1478
+ coupled network) or IL (stabilization of coupling)
1479
+
1480
+ Examples
1481
+ --------
1482
+ **Technical Example:**
1483
+
1484
+ >>> from tnfr.constants import DNFR_PRIMARY, THETA_PRIMARY, VF_PRIMARY
1485
+ >>> from tnfr.dynamics import set_delta_nfr_hook
1486
+ >>> from tnfr.structural import create_nfr, run_sequence
1487
+ >>> from tnfr.operators.definitions import Coupling
1488
+ >>> G, node = create_nfr("pair", vf=1.20, theta=0.50)
1489
+ >>> alignments = iter([(-0.18, 0.03, 0.02)])
1490
+ >>> def synchronise(graph):
1491
+ ... d_theta, d_vf, residual_dnfr = next(alignments)
1492
+ ... graph.nodes[node][THETA_PRIMARY] += d_theta
1493
+ ... graph.nodes[node][VF_PRIMARY] += d_vf
1494
+ ... graph.nodes[node][DNFR_PRIMARY] = residual_dnfr
1495
+ >>> set_delta_nfr_hook(G, synchronise)
1496
+ >>> run_sequence(G, node, [Coupling()])
1497
+ >>> round(G.nodes[node][THETA_PRIMARY], 2)
1498
+ 0.32
1499
+ >>> round(G.nodes[node][VF_PRIMARY], 2)
1500
+ 1.23
1501
+ >>> round(G.nodes[node][DNFR_PRIMARY], 2)
1502
+ 0.02
1503
+
1504
+ **Example (Heart-Brain Coherence):**
1505
+
1506
+ >>> # Coupling cardiac and neural rhythms during meditation
1507
+ >>> G_body, heart_brain = create_nfr("heart_brain_system", vf=1.20, theta=0.50)
1508
+ >>> # Separate rhythms initially (phase difference 0.50)
1509
+ >>> # UM: Coherent breathing synchronizes heart and brain
1510
+ >>> run_sequence(G_body, heart_brain, [Coupling()])
1511
+ >>> # Result: Phases converge (θ reduces to ~0.32)
1512
+ >>> # Heart and brain enter coupled coherent state
1513
+ >>> # Creates platform for RA (coherence propagation to body)
1514
+
1515
+ **Example (Collaborative Learning):**
1516
+
1517
+ >>> # Students forming shared understanding in group work
1518
+ >>> G_group, team = create_nfr("study_group", vf=1.10, theta=0.45)
1519
+ >>> # Individual understandings initially misaligned
1520
+ >>> # UM: Discussion and explanation synchronize mental models
1521
+ >>> run_sequence(G_group, team, [Coupling()])
1522
+ >>> # Result: Conceptual phases align, confusion reduces
1523
+ >>> # Shared understanding emerges, enables THOL (group insight)
1524
+
1525
+ See Also
1526
+ --------
1527
+ Resonance : Propagates through coupled networks
1528
+ Coherence : Stabilizes couplings
1529
+ SelfOrganization : Emerges from multiple couplings
1530
+ """
1531
+
1532
+ __slots__ = ()
1533
+ name: ClassVar[str] = COUPLING
1534
+ glyph: ClassVar[Glyph] = Glyph.UM
1535
+
1536
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
1537
+ """Validate UM-specific preconditions."""
1538
+ from .preconditions import validate_coupling
1539
+
1540
+ validate_coupling(G, node)
1541
+
1542
+ def _capture_state(self, G: TNFRGraph, node: Any) -> dict[str, Any]:
1543
+ """Capture node state before operator application, including edge count."""
1544
+ # Get base state (epi, vf, dnfr, theta)
1545
+ state = super()._capture_state(G, node)
1546
+
1547
+ # Add edge count for coupling-specific metrics
1548
+ state["edges"] = G.degree(node)
1549
+
1550
+ return state
1551
+
1552
+ def _collect_metrics(
1553
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
1554
+ ) -> dict[str, Any]:
1555
+ """Collect UM-specific metrics with expanded canonical measurements."""
1556
+ from .metrics import coupling_metrics
1557
+
1558
+ return coupling_metrics(
1559
+ G,
1560
+ node,
1561
+ state_before["theta"],
1562
+ dnfr_before=state_before["dnfr"],
1563
+ vf_before=state_before["vf"],
1564
+ edges_before=state_before.get("edges", None),
1565
+ epi_before=state_before["epi"],
1566
+ )
1567
+
1568
+
1569
+ @register_operator
1570
+ class Resonance(Operator):
1571
+ """Resonance structural operator (RA) - Network coherence propagation.
1572
+
1573
+ Activates glyph ``RA`` to circulate phase-aligned energy through the network,
1574
+ amplifying shared frequency and propagating coherent resonance between nodes.
1575
+
1576
+ TNFR Context
1577
+ ------------
1578
+ Resonance (RA) is the propagation mechanism in TNFR networks. When nodes are coupled
1579
+ and phase-aligned, RA transmits coherence (EPIₙ → EPIₙ₊₁) without loss of structural
1580
+ identity. This creates "resonant cascades" where coherence amplifies across the
1581
+ network, increasing collective νf and global C(t). RA embodies the fundamental TNFR
1582
+ principle: structural patterns propagate through resonance, not mechanical transfer.
1583
+
1584
+ **Key Elements:**
1585
+
1586
+ - **Identity Preservation**: Propagated EPI maintains structural integrity
1587
+ - **Amplification**: Coherence strengthens through resonant networks
1588
+ - **Phase Alignment**: Requires synchronized nodes (UM prerequisite)
1589
+ - **Network Emergence**: Creates collective coherence beyond individual nodes
1590
+
1591
+ Use Cases
1592
+ ---------
1593
+ **Biomedical**:
1594
+
1595
+ - **Cardiac Coherence Propagation**
1596
+
1597
+ - **Mechanism**: HRV coherence from heart rhythm spreads through vagal nerve network
1598
+ - **RA Role**: Propagates coherent cardiac pattern to brain, organs, peripheral systems
1599
+ - **Observable**: Reduced heart rate variability entropy, increased baroreflex sensitivity
1600
+ - **Sequence**: AL (heart initiates) → IL (stabilizes rhythm) → RA (spreads to body)
1601
+ - **Metrics**: ΔHRV coherence across organ systems, autonomic tone synchronization
1602
+
1603
+ - **Neural Synchronization Cascades**
1604
+
1605
+ - **Mechanism**: Synchronized neuronal firing in one region propagates to connected areas
1606
+ - **RA Role**: Transmits oscillatory patterns (e.g., gamma, theta) across brain networks
1607
+ - **Observable**: EEG phase synchronization indices, functional connectivity increases
1608
+ - **Sequence**: THOL (local synchrony emerges) → UM (regions couple) → RA (network sync)
1609
+ - **Clinical**: Meditation-induced alpha coherence, seizure propagation dynamics
1610
+
1611
+ - **Immune Cascade Activation**
1612
+
1613
+ - **Mechanism**: Cytokine signaling propagates immune response across tissue
1614
+ - **RA Role**: Coordinates cellular activation without losing response specificity
1615
+ - **Observable**: Immune cell recruitment patterns, synchronized cytokine expression
1616
+ - **Pathological**: Cytokine storms as uncontrolled RA (missing IL stabilization)
1617
+
1618
+ - **Morphogenetic Field Propagation**
1619
+
1620
+ - **Mechanism**: Developmental signals organize tissue pattern formation
1621
+ - **RA Role**: Spreads positional information maintaining structural identity
1622
+ - **Observable**: Hox gene expression gradients, limb bud patterning
1623
+ - **TNFR Model**: RA preserves EPI identity (cell type) while propagating position
1624
+
1625
+ **Cognitive**:
1626
+
1627
+ - **Insight Propagation ("Aha!" Moments)**
1628
+
1629
+ - **Mechanism**: Single conceptual breakthrough reorganizes entire knowledge network
1630
+ - **RA Role**: Key understanding cascades through related concepts, illuminating connections
1631
+ - **Observable**: Sudden problem-solving, gestalt shifts, conceptual restructuring
1632
+ - **Sequence**: OZ (conceptual tension) → THOL (insight emerges) → RA (understanding spreads)
1633
+ - **Example**: Understanding recursion suddenly clarifies programming, fractals, self-reference
1634
+
1635
+ - **Meme Propagation**
1636
+
1637
+ - **Mechanism**: Ideas spread through population maintaining core structure
1638
+ - **RA Role**: Transmits conceptual pattern ("viral" spread) with identity preservation
1639
+ - **Observable**: Social media virality curves, idea adoption S-curves
1640
+ - **Pathological**: Misinformation spread (RA without IL verification)
1641
+ - **Counter**: IL (fact-checking) dampens incoherent RA
1642
+
1643
+ - **Knowledge Transfer in Learning**
1644
+
1645
+ - **Mechanism**: Expertise propagates from teacher to student network
1646
+ - **RA Role**: Transmits structured understanding, not just information
1647
+ - **Observable**: Student mental models converging toward expert patterns
1648
+ - **Sequence**: EN (student receives) → IL (integrates) → RA (applies to new contexts)
1649
+ - **Metrics**: Transfer learning success, analogical reasoning improvements
1650
+
1651
+ - **Attention Cascades**
1652
+
1653
+ - **Mechanism**: Focus on one element draws attention to connected elements
1654
+ - **RA Role**: Spreads attentional coherence across semantic network
1655
+ - **Observable**: Priming effects, associative memory activation
1656
+ - **Example**: Seeing "doctor" activates "nurse", "hospital", "stethoscope"
1657
+
1658
+ **Social**:
1659
+
1660
+ - **Collective Emotional Contagion**
1661
+
1662
+ - **Mechanism**: Emotion spreads through group (laughter, panic, enthusiasm)
1663
+ - **RA Role**: Propagates affective state while maintaining emotional coherence
1664
+ - **Observable**: Synchronized facial expressions, heart rate convergence, mirroring
1665
+ - **Sequence**: AL (individual expresses) → UM (others attune) → RA (group synchrony)
1666
+ - **Examples**: Concert crowds, protest movements, team celebrations
1667
+
1668
+ - **Social Movement Diffusion**
1669
+
1670
+ - **Mechanism**: Values/practices spread through social networks
1671
+ - **RA Role**: Propagates coherent ideology maintaining identity
1672
+ - **Observable**: Network diffusion curves, hashtag propagation, adoption cascades
1673
+ - **Critical Mass**: RA accelerates post-UM (coupling) threshold
1674
+ - **Examples**: Arab Spring, #MeToo, climate activism
1675
+
1676
+ - **Innovation Diffusion in Organizations**
1677
+
1678
+ - **Mechanism**: New practices spread through company departments
1679
+ - **RA Role**: Transfers best practices while adapting to local context
1680
+ - **Observable**: Practice adoption rates, cross-functional knowledge sharing
1681
+ - **Sequence**: THOL (innovation emerges) → UM (early adopters couple) → RA (spreads)
1682
+ - **Barriers**: OZ (departmental resistance) can block RA
1683
+
1684
+ - **Cultural Pattern Transmission**
1685
+
1686
+ - **Mechanism**: Rituals, norms, symbols propagate across generations
1687
+ - **RA Role**: Maintains cultural identity while allowing adaptation
1688
+ - **Observable**: Cultural continuity metrics, tradition persistence
1689
+ - **Balance**: RA (preservation) vs ZHIR (cultural evolution)
1690
+
1691
+ Typical Sequences
1692
+ ---------------------------
1693
+ - **UM → RA**: Coupling followed by propagation (network activation)
1694
+ - **AL → RA**: Emission followed by propagation (broadcast pattern)
1695
+ - **RA → IL**: Resonance stabilized (network coherence lock)
1696
+ - **IL → RA**: Stable form propagated (controlled spread)
1697
+ - **RA → EN**: Propagation received (network reception)
1698
+
1699
+ Preconditions
1700
+ -------------
1701
+ - Source node must have coherent EPI
1702
+ - Network connectivity must exist (edges)
1703
+ - Phase compatibility between nodes (coupling)
1704
+ - Sufficient νf to support propagation
1705
+
1706
+ Structural Effects
1707
+ ------------------
1708
+ - **Network EPI**: Propagates to connected nodes
1709
+ - **Collective νf**: Amplifies across network
1710
+ - **Global C(t)**: Increases through network coherence
1711
+ - **ΔNFR**: May slightly increase initially, then stabilize
1712
+ - **Phase alignment**: Strengthens across propagation path
1713
+
1714
+ Metrics
1715
+ -------
1716
+ **Propagation Metrics**:
1717
+
1718
+ - **Propagation Distance**: Number of nodes reached from source
1719
+
1720
+ - Measurement: Graph traversal depth from origin
1721
+ - Healthy: Distance scales with network density
1722
+ - Pathological: Isolated propagation (missing UM coupling)
1723
+
1724
+ - **Amplification Factor**: Coherence gain through network
1725
+
1726
+ - Formula: ``C(t_after) / C(t_before)`` at network level
1727
+ - Healthy: Factor > 1.0 (resonance amplifies)
1728
+ - Degraded: Factor ≈ 1.0 (diffusion without resonance)
1729
+
1730
+ - **Propagation Speed**: Rate of coherence spread
1731
+
1732
+ - Measurement: Nodes activated per time step
1733
+ - Fast: High νf alignment, strong UM coupling
1734
+ - Slow: Phase misalignment, weak network connectivity
1735
+
1736
+ **Identity Preservation Metrics**:
1737
+
1738
+ - **EPI Structure Similarity**: How well propagated EPI matches source
1739
+
1740
+ - Measurement: Cosine similarity of EPI vectors (if structured)
1741
+ - Healthy: Similarity > 0.8 (identity preserved)
1742
+ - Distorted: Similarity < 0.5 (pattern corruption)
1743
+
1744
+ - **epi_kind Consistency**: Semantic label propagation
1745
+
1746
+ - Measurement: Fraction of influenced nodes adopting source ``epi_kind``
1747
+ - Healthy: > 70% adoption in coupled neighborhood
1748
+ - Fragmented: < 30% (RA failed, revert to AL)
1749
+
1750
+ **Network-Level Metrics**:
1751
+
1752
+ - **Global Coherence Increase (ΔC(t))**:
1753
+
1754
+ - Formula: ``C_global(t+1) - C_global(t)`` after RA application
1755
+ - Healthy: ΔC(t) > 0 (network more coherent)
1756
+ - Harmful: ΔC(t) < 0 (RA applied incorrectly, spreading chaos)
1757
+
1758
+ - **Phase Synchronization Index**:
1759
+
1760
+ - Measurement: Kuramoto order parameter before/after RA
1761
+ - Healthy: Index increases toward 1.0
1762
+ - Misaligned: Index decreases (needs UM first)
1763
+
1764
+ **Frequency Metrics**:
1765
+
1766
+ - **Collective νf Shift**: Average νf change across influenced nodes
1767
+
1768
+ - Measurement: ``mean(νf_influenced) - mean(νf_before)``
1769
+ - Healthy: Positive shift (amplification)
1770
+ - Note: Current implementation may not fully track this (see related issues)
1771
+
1772
+ Compatibility
1773
+ -------------
1774
+ **Synergistic Sequences** (amplify each other's effects):
1775
+
1776
+ - **UM → RA**: Canonical resonance pattern
1777
+
1778
+ - UM establishes phase coupling
1779
+ - RA propagates through coupled network
1780
+ - Result: Coherent network-wide reorganization
1781
+ - Analogy: Tuning instruments (UM) then playing symphony (RA)
1782
+
1783
+ - **IL → RA**: Stable propagation
1784
+
1785
+ - IL stabilizes source pattern
1786
+ - RA propagates verified coherence
1787
+ - Result: Reliable, non-distorted transmission
1788
+ - Use: Knowledge transfer, cultural preservation
1789
+
1790
+ - **AL → RA**: Broadcast pattern
1791
+
1792
+ - AL initiates new coherence
1793
+ - RA immediately spreads to receptive nodes
1794
+ - Result: Rapid network activation
1795
+ - Use: Idea dissemination, emotional contagion
1796
+ - Risk: Unstable if AL not stabilized (add IL between)
1797
+
1798
+ **Required Prerequisites** (apply before RA):
1799
+
1800
+ - **UM before RA** (when network uncoupled):
1801
+
1802
+ - Without UM: RA has no propagation pathways
1803
+ - Symptom: RA applied to isolated node
1804
+ - Fix: ``run_sequence(G, node, [Coupling(), Resonance()])``
1805
+
1806
+ - **IL before RA** (when source unstable):
1807
+
1808
+ - Without IL: RA propagates noise/chaos
1809
+ - Symptom: High ΔNFR, low EPI at source
1810
+ - Fix: ``run_sequence(G, node, [Coherence(), Resonance()])``
1811
+
1812
+ **Natural Progressions** (what to apply after RA):
1813
+
1814
+ - **RA → IL**: Lock in propagated coherence
1815
+
1816
+ - RA spreads pattern
1817
+ - IL stabilizes across network
1818
+ - Result: Persistent network-wide coherence
1819
+ - Example: Post-meditation integration, learning consolidation
1820
+
1821
+ - **RA → EN**: Distributed reception
1822
+
1823
+ - RA broadcasts from source
1824
+ - EN nodes receive and integrate
1825
+ - Result: Coordinated network update
1826
+ - Example: Software update propagation, news dissemination
1827
+
1828
+ - **RA → SHA**: Resonance completion
1829
+
1830
+ - RA propagates pattern
1831
+ - SHA pauses further spreading
1832
+ - Result: Bounded coherence domain
1833
+ - Example: Localized neural assembly, cultural enclave
1834
+
1835
+ **Incompatible Patterns** (avoid or use carefully):
1836
+
1837
+ - **SHA → RA**: Contradiction
1838
+
1839
+ - SHA silences node (νf → 0)
1840
+ - RA requires active propagation
1841
+ - Result: Ineffective RA (nothing to propagate)
1842
+ - Exception: SHA → NAV → RA (reactivation sequence)
1843
+
1844
+ - **OZ → RA** (unconstrained dissonance):
1845
+
1846
+ - OZ introduces chaos
1847
+ - RA propagates chaos (pathological)
1848
+ - Result: Network destabilization
1849
+ - Safe: OZ → IL → RA (constrain dissonance first)
1850
+ - Intentional: OZ → RA for creative disruption (rare)
1851
+
1852
+ - **Multiple RA without IL**:
1853
+
1854
+ - Repeated RA can blur pattern identity
1855
+ - Result: "Telephone game" distortion
1856
+ - Fix: Interleave IL to preserve structure
1857
+ - Pattern: RA → IL → RA → IL (controlled cascade)
1858
+
1859
+ **Edge Cases**:
1860
+
1861
+ - **RA on fully connected graph**:
1862
+
1863
+ - All nodes receive simultaneously
1864
+ - Result: Instantaneous network coherence (no cascade)
1865
+ - Efficiency: RA becomes equivalent to broadcast AL
1866
+
1867
+ - **RA on tree topology**:
1868
+
1869
+ - Clean propagation paths, no loops
1870
+ - Result: Predictable cascade from root
1871
+ - Application: Hierarchical organizations, decision trees
1872
+
1873
+ - **RA on scale-free network**:
1874
+
1875
+ - Hub nodes amplify propagation
1876
+ - Result: Exponential spread through hubs
1877
+ - Application: Social networks, viral marketing
1878
+ - Risk: Hub failure blocks cascade (fragile)
1879
+
1880
+ Examples
1881
+ --------
1882
+ **Technical Example:**
1883
+
1884
+ >>> from tnfr.constants import DNFR_PRIMARY, VF_PRIMARY
1885
+ >>> from tnfr.dynamics import set_delta_nfr_hook
1886
+ >>> from tnfr.structural import create_nfr, run_sequence
1887
+ >>> from tnfr.operators.definitions import Resonance
1888
+ >>> G, node = create_nfr("carrier", vf=0.90)
1889
+ >>> pulses = iter([(0.05, 0.03)])
1890
+ >>> def amplify(graph):
1891
+ ... d_vf, d_dnfr = next(pulses)
1892
+ ... graph.nodes[node][VF_PRIMARY] += d_vf
1893
+ ... graph.nodes[node][DNFR_PRIMARY] = d_dnfr
1894
+ >>> set_delta_nfr_hook(G, amplify)
1895
+ >>> run_sequence(G, node, [Resonance()])
1896
+ >>> round(G.nodes[node][VF_PRIMARY], 2)
1897
+ 0.95
1898
+ >>> round(G.nodes[node][DNFR_PRIMARY], 2)
1899
+ 0.03
1900
+
1901
+ **Example (Cardiac Coherence Spread):**
1902
+
1903
+ >>> # Heart coherence propagating to entire nervous system
1904
+ >>> G_body, heart = create_nfr("cardiac_source", vf=0.90, epi=0.60)
1905
+ >>> # Heart achieves coherent state (IL), now propagating
1906
+ >>> # RA: Coherent rhythm spreads through vagal nerve network
1907
+ >>> run_sequence(G_body, heart, [Resonance()])
1908
+ >>> # Result: Coherence propagates to brain, organs, peripheral systems
1909
+ >>> # Whole body enters resonant coherent state
1910
+ >>> # Enables healing, relaxation, optimal function
1911
+
1912
+ **Example (Insight Cascade):**
1913
+
1914
+ >>> # Understanding suddenly spreading through mental model
1915
+ >>> G_mind, insight = create_nfr("conceptual_breakthrough", vf=1.05, epi=0.55)
1916
+ >>> # Key insight achieved (THOL), now propagating
1917
+ >>> # RA: Understanding cascades through related concepts
1918
+ >>> run_sequence(G_mind, insight, [Resonance()])
1919
+ >>> # Result: Single insight illuminates entire knowledge domain
1920
+ >>> # "Aha!" moment as coherence spreads through mental network
1921
+ >>> # Previously disconnected ideas suddenly align
1922
+
1923
+ **Example (Social Movement):**
1924
+
1925
+ >>> # Idea resonating through social network
1926
+ >>> G_social, movement = create_nfr("cultural_idea", vf=0.95, epi=0.50)
1927
+ >>> # Coherent message formed (IL), now spreading
1928
+ >>> # RA: Idea propagates through connected communities
1929
+ >>> run_sequence(G_social, movement, [Resonance()])
1930
+ >>> # Result: Message amplifies across network
1931
+ >>> # More nodes adopt and propagate the pattern
1932
+ >>> # Creates collective coherence and momentum
1933
+
1934
+ **Example (Meditation Group Coherence):**
1935
+
1936
+ >>> # Meditation teacher establishes coherent state, propagates to students
1937
+ >>> import networkx as nx
1938
+ >>> import random
1939
+ >>> from tnfr.structural import create_nfr, run_sequence
1940
+ >>> from tnfr.operators.definitions import Coupling, Resonance
1941
+ >>> from tnfr.metrics.coherence import compute_global_coherence
1942
+ >>> from tnfr.constants import EPI_PRIMARY
1943
+ >>>
1944
+ >>> G_meditation = nx.Graph()
1945
+ >>> # Teacher with high coherence
1946
+ >>> G_meditation.add_node("teacher")
1947
+ >>> G_meditation.nodes["teacher"][EPI_PRIMARY] = 0.85
1948
+ >>> G_meditation.nodes["teacher"]["vf"] = 1.2
1949
+ >>> G_meditation.nodes["teacher"]["theta"] = 0.0
1950
+ >>>
1951
+ >>> # Students with lower coherence, varied phases
1952
+ >>> for i in range(10):
1953
+ ... student_id = f"student_{i}"
1954
+ ... G_meditation.add_node(student_id)
1955
+ ... G_meditation.nodes[student_id][EPI_PRIMARY] = 0.3
1956
+ ... G_meditation.nodes[student_id]["vf"] = 0.9
1957
+ ... G_meditation.nodes[student_id]["theta"] = random.uniform(-0.5, 0.5)
1958
+ ... # Teacher couples with students through presence (UM)
1959
+ ... G_meditation.add_edge("teacher", student_id)
1960
+ >>>
1961
+ >>> # Teacher's coherence resonates to group (RA)
1962
+ >>> c_before = compute_global_coherence(G_meditation)
1963
+ >>> run_sequence(G_meditation, "teacher", [Coupling(), Resonance()])
1964
+ >>> c_after = compute_global_coherence(G_meditation)
1965
+ >>>
1966
+ >>> # Result: Students' EPI increases, phases align, network coherence rises
1967
+ >>> # Group enters synchronized meditative state through RA propagation
1968
+
1969
+ **Example (Viral Meme Cascade):**
1970
+
1971
+ >>> # Idea originates, couples with early adopters, resonates through network
1972
+ >>> import networkx as nx
1973
+ >>> from tnfr.structural import run_sequence
1974
+ >>> from tnfr.operators.definitions import Coupling, Resonance
1975
+ >>> from tnfr.constants import EPI_PRIMARY
1976
+ >>>
1977
+ >>> G_social = nx.barabasi_albert_graph(100, 3) # Scale-free social network
1978
+ >>> origin = 0 # Hub node with high connectivity
1979
+ >>>
1980
+ >>> # Set initial state: one coherent idea, rest neutral
1981
+ >>> for node in G_social.nodes():
1982
+ ... G_social.nodes[node][EPI_PRIMARY] = 0.9 if node == origin else 0.1
1983
+ ... G_social.nodes[node]["vf"] = 1.0
1984
+ ... G_social.nodes[node]["epi_kind"] = "viral_meme" if node == origin else "neutral"
1985
+ ... G_social.nodes[node]["theta"] = 0.0
1986
+ >>>
1987
+ >>> # Phase 1: Early adopters couple with origin (UM)
1988
+ >>> run_sequence(G_social, origin, [Coupling()])
1989
+ >>>
1990
+ >>> # Phase 2: Idea resonates through coupled network (RA)
1991
+ >>> adoption_wave = [origin]
1992
+ >>> for wave_step in range(5): # 5 propagation hops
1993
+ ... for node in list(adoption_wave):
1994
+ ... run_sequence(G_social, node, [Resonance()])
1995
+ ... # Add newly influenced nodes to wave
1996
+ ... for neighbor in G_social.neighbors(node):
1997
+ ... if G_social.nodes[neighbor][EPI_PRIMARY] > 0.5 and neighbor not in adoption_wave:
1998
+ ... adoption_wave.append(neighbor)
1999
+ >>>
2000
+ >>> # Result: Meme spreads through network maintaining identity
2001
+ >>> adopters = [n for n in G_social.nodes() if G_social.nodes[n].get("epi_kind") == "viral_meme"]
2002
+ >>> adoption_rate = len(adopters) / 100
2003
+ >>> # Demonstrates RA creating resonant cascade through scale-free topology
2004
+
2005
+ See Also
2006
+ --------
2007
+ Coupling : Creates conditions for RA propagation
2008
+ Coherence : Stabilizes resonant patterns
2009
+ Emission : Initiates patterns for RA to propagate
2010
+ """
2011
+
2012
+ __slots__ = ()
2013
+ name: ClassVar[str] = RESONANCE
2014
+ glyph: ClassVar[Glyph] = Glyph.RA
2015
+
2016
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
2017
+ """Validate RA-specific preconditions."""
2018
+ from .preconditions import validate_resonance
2019
+
2020
+ validate_resonance(G, node)
2021
+
2022
+ def _collect_metrics(
2023
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
2024
+ ) -> dict[str, Any]:
2025
+ """Collect RA-specific metrics with canonical νf amplification tracking."""
2026
+ from .metrics import resonance_metrics
2027
+
2028
+ return resonance_metrics(
2029
+ G,
2030
+ node,
2031
+ state_before["epi"],
2032
+ vf_before=state_before["vf"], # Include νf for amplification tracking
2033
+ )
2034
+
2035
+
2036
+ @register_operator
2037
+ class Silence(Operator):
2038
+ """Silence structural operator (SHA) - Preservation through structural pause.
2039
+
2040
+ Activates glyph ``SHA`` to lower νf and hold the local EPI invariant, suspending
2041
+ reorganization to preserve the node's current coherence state. SHA implements
2042
+ **latency state management** with explicit temporal tracking.
2043
+
2044
+ TNFR Context
2045
+ ------------
2046
+ Silence (SHA) creates structural latency - a state where νf ≈ 0, causing the nodal
2047
+ equation ∂EPI/∂t = νf · ΔNFR(t) to approach zero regardless of ΔNFR. This preserves
2048
+ the current EPI form intact, preventing reorganization. SHA is essential for memory,
2049
+ consolidation, and maintaining structural identity during network turbulence.
2050
+
2051
+ According to TNFR.pdf §2.3.10, SHA is not merely frequency reduction but a
2052
+ **transition to latent state** with temporal tracking for analyzing memory
2053
+ consolidation, incubation periods, and protective pauses.
2054
+
2055
+ **Key Elements:**
2056
+
2057
+ - **Frequency Suppression**: Reduces νf to near-zero (structural pause)
2058
+ - **Form Preservation**: EPI remains unchanged despite external pressures
2059
+ - **Latent Memory**: Stored patterns awaiting reactivation
2060
+ - **Strategic Inaction**: Deliberate non-reorganization as protective mechanism
2061
+ - **Temporal Tracking**: Explicit duration and state management
2062
+
2063
+ Use Cases
2064
+ ---------
2065
+ **Biomedical**:
2066
+
2067
+ - **Rest and Recovery**: Physiological downregulation for healing
2068
+ - **Sleep Consolidation**: Memory formation through structural pause
2069
+ - **Meditation States**: Conscious reduction of mental reorganization
2070
+ - **Trauma Containment**: Protective numbing of overwhelming activation
2071
+
2072
+ **Cognitive**:
2073
+
2074
+ - **Memory Storage**: Consolidating learning through reduced interference
2075
+ - **Incubation Period**: Letting problems "rest" before insight
2076
+ - **Attention Rest**: Recovery from cognitive load
2077
+ - **Knowledge Preservation**: Maintaining expertise without active use
2078
+
2079
+ **Social**:
2080
+
2081
+ - **Strategic Pause**: Deliberate non-action in conflict
2082
+ - **Cultural Preservation**: Maintaining traditions without active practice
2083
+ - **Organizational Stability**: Resisting change pressure
2084
+ - **Waiting Strategy**: Preserving position until conditions favor action
2085
+
2086
+ Typical Sequences
2087
+ ---------------------------
2088
+ - **IL → SHA**: Stabilize then preserve (long-term memory)
2089
+ - **SHA → IL → AL**: Silence → stabilization → reactivation (coherent awakening)
2090
+ - **SHA → EN → IL**: Silence → external reception → stabilization (network reactivation)
2091
+ - **SHA → NAV**: Preserved structure transitions (controlled change)
2092
+ - **OZ → SHA**: Dissonance contained (protective pause)
2093
+
2094
+ **AVOID**: SHA → AL (direct reactivation violates structural continuity - requires intermediate stabilization)
2095
+ **AVOID**: SHA → OZ (silence followed by dissonance contradicts preservation)
2096
+ **AVOID**: SHA → SHA (redundant, no structural purpose)
2097
+
2098
+ Preconditions
2099
+ -------------
2100
+ - Node must have existing EPI to preserve
2101
+ - Network pressure (ΔNFR) should not be critically high
2102
+ - Context must support reduced activity
2103
+
2104
+ Structural Effects
2105
+ ------------------
2106
+ - **νf**: Significantly reduced (≈ 0, primary effect)
2107
+ - **EPI**: Held invariant (preservation)
2108
+ - **ΔNFR**: Neither increases nor decreases (frozen state)
2109
+ - **θ**: Maintained but not actively synchronized
2110
+ - **Network influence**: Minimal during silence
2111
+
2112
+ Latency State Attributes
2113
+ -------------------------
2114
+ SHA sets the following node attributes for latency tracking:
2115
+
2116
+ - **latent**: Boolean flag indicating node is in latent state
2117
+ - **latency_start_time**: ISO 8601 UTC timestamp when silence began
2118
+ - **preserved_epi**: Snapshot of EPI at silence entry
2119
+ - **silence_duration**: Cumulative duration in latent state (updated on subsequent steps)
2120
+
2121
+ Metrics
2122
+ -----------------
2123
+ - νf reduction: Degree of frequency suppression
2124
+ - EPI stability: Variance over silence period (should be ~0)
2125
+ - Silence duration: Time in latent state
2126
+ - Preservation effectiveness: EPI integrity post-silence
2127
+ - Preservation integrity: Measures EPI variance during silence
2128
+
2129
+ Compatibility
2130
+ ---------------------
2131
+ **Compatible with**: IL (Coherence before silence), NAV (Transition from silence),
2132
+ AL (Reactivation from silence)
2133
+
2134
+ **Avoid with**: OZ (Dissonance), RA (Resonance), multiple consecutive operators
2135
+
2136
+ **Natural progressions**: SHA typically ends sequences or precedes reactivation
2137
+ (AL) or transition (NAV)
2138
+
2139
+ Examples
2140
+ --------
2141
+ **Technical Example:**
2142
+
2143
+ >>> from tnfr.constants import DNFR_PRIMARY, EPI_PRIMARY, VF_PRIMARY
2144
+ >>> from tnfr.dynamics import set_delta_nfr_hook
2145
+ >>> from tnfr.structural import create_nfr, run_sequence
2146
+ >>> from tnfr.operators.definitions import Silence
2147
+ >>> G, node = create_nfr("rest", epi=0.51, vf=1.00)
2148
+ >>> def freeze(graph):
2149
+ ... graph.nodes[node][DNFR_PRIMARY] = 0.0
2150
+ ... graph.nodes[node][VF_PRIMARY] = 0.02
2151
+ ... # EPI is intentionally left untouched to preserve the stored form.
2152
+ >>> set_delta_nfr_hook(G, freeze)
2153
+ >>> run_sequence(G, node, [Silence()])
2154
+ >>> round(G.nodes[node][EPI_PRIMARY], 2)
2155
+ 0.51
2156
+ >>> round(G.nodes[node][VF_PRIMARY], 2)
2157
+ 0.02
2158
+
2159
+ **Example (Sleep Consolidation):**
2160
+
2161
+ >>> # Memory consolidation during sleep
2162
+ >>> G_memory, memory_trace = create_nfr("learned_pattern", epi=0.51, vf=1.00)
2163
+ >>> # Pattern learned during day (IL stabilized)
2164
+ >>> # SHA: Deep sleep reduces neural activity, preserves memory
2165
+ >>> run_sequence(G_memory, memory_trace, [Silence()])
2166
+ >>> # Result: EPI preserved intact (0.51 unchanged)
2167
+ >>> # νf drops to near-zero, prevents interference
2168
+ >>> # Memory consolidates through structural silence
2169
+
2170
+ **Example (Meditative Rest):**
2171
+
2172
+ >>> # Consciousness entering deep meditation
2173
+ >>> G_mind, awareness = create_nfr("mental_state", epi=0.48, vf=0.95)
2174
+ >>> # Active mind state before meditation
2175
+ >>> # SHA: Meditation reduces mental activity, preserves presence
2176
+ >>> run_sequence(G_mind, awareness, [Silence()])
2177
+ >>> # Result: Mental chatter ceases (νf → 0)
2178
+ >>> # Awareness EPI maintained without elaboration
2179
+ >>> # Restful alertness through structural silence
2180
+
2181
+ **Example (Organizational Pause):**
2182
+
2183
+ >>> # Company maintaining position during market uncertainty
2184
+ >>> G_company, strategy = create_nfr("business_position", epi=0.55, vf=1.10)
2185
+ >>> # Established strategy under pressure to change
2186
+ >>> # SHA: Leadership decides to "wait and see"
2187
+ >>> run_sequence(G_company, strategy, [Silence()])
2188
+ >>> # Result: Strategy preserved without modification
2189
+ >>> # Organization resists external pressure for change
2190
+ >>> # Maintains identity until conditions clarify
2191
+
2192
+ See Also
2193
+ --------
2194
+ Coherence : Often precedes SHA for stable preservation
2195
+ Transition : Breaks silence with controlled change
2196
+ Emission : Reactivates silenced structures
2197
+
2198
+ Extended Clinical Documentation
2199
+ --------------------------------
2200
+ For detailed clinical protocols, expected telemetry, physiological correlates,
2201
+ and scientific references, see:
2202
+
2203
+ **docs/source/examples/SHA_CLINICAL_APPLICATIONS.md**
2204
+
2205
+ Comprehensive documentation includes:
2206
+ - Cardiac Coherence Training (HRV consolidation)
2207
+ - Trauma Therapy (protective containment)
2208
+ - Sleep & Memory Consolidation (neuroscience applications)
2209
+ - Post-Exercise Recovery (athletic training)
2210
+ - Meditation & Mindfulness (contemplative practices)
2211
+ - Organizational Strategy (strategic pause protocols)
2212
+
2213
+ **Executable Examples**: examples/biomedical/
2214
+ - cardiac_coherence_sha.py
2215
+ - trauma_containment_sha.py
2216
+ - sleep_consolidation_sha.py
2217
+ - recovery_protocols_sha.py
2218
+ """
2219
+
2220
+ __slots__ = ()
2221
+ name: ClassVar[str] = SILENCE
2222
+ glyph: ClassVar[Glyph] = Glyph.SHA
2223
+
2224
+ def __call__(self, G: TNFRGraph, node: Any, **kw: Any) -> None:
2225
+ """Apply SHA with latency state tracking.
2226
+
2227
+ Establishes latency state before delegating to grammar execution.
2228
+ This ensures every silence operation creates explicit latent state
2229
+ tracking as required by TNFR.pdf §2.3.10 (SHA - Silencio estructural).
2230
+
2231
+ Parameters
2232
+ ----------
2233
+ G : TNFRGraph
2234
+ Graph storing TNFR nodes and structural operator history.
2235
+ node : Any
2236
+ Identifier or object representing the target node within ``G``.
2237
+ **kw : Any
2238
+ Additional keyword arguments forwarded to the grammar layer.
2239
+ """
2240
+ # Mark latency state BEFORE grammar execution
2241
+ self._mark_latency_state(G, node)
2242
+
2243
+ # Delegate to parent __call__ which applies grammar
2244
+ super().__call__(G, node, **kw)
2245
+
2246
+ def _mark_latency_state(self, G: TNFRGraph, node: Any) -> None:
2247
+ """Mark latency state for SHA operator.
2248
+
2249
+ According to TNFR.pdf §2.3.10, SHA implements structural silence
2250
+ with temporal tracking for memory consolidation and protective pauses.
2251
+
2252
+ This method establishes:
2253
+ - Latent flag: Boolean indicating node is in latent state
2254
+ - Temporal marker: ISO timestamp when silence began
2255
+ - Preserved EPI: Snapshot of EPI for integrity verification
2256
+ - Duration tracker: Cumulative time in silence (initialized to 0)
2257
+
2258
+ Parameters
2259
+ ----------
2260
+ G : TNFRGraph
2261
+ Graph containing the node.
2262
+ node : Any
2263
+ Target node for silence marking.
2264
+
2265
+ Notes
2266
+ -----
2267
+ Sets the following node attributes:
2268
+ - latent: True (node in latent state)
2269
+ - latency_start_time: ISO 8601 UTC timestamp
2270
+ - preserved_epi: Current EPI value snapshot
2271
+ - silence_duration: 0.0 (initialized, updated by external time tracking)
2272
+ """
2273
+ from datetime import datetime, timezone
2274
+
2275
+ from ..alias import get_attr
2276
+
2277
+ # Always set latency state (SHA can be applied multiple times)
2278
+ G.nodes[node]["latent"] = True
2279
+
2280
+ # Set start time for this latency period
2281
+ latency_start_time = datetime.now(timezone.utc).isoformat()
2282
+ G.nodes[node]["latency_start_time"] = latency_start_time
2283
+
2284
+ # Preserve current EPI for integrity checking
2285
+ epi_value = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
2286
+ G.nodes[node]["preserved_epi"] = epi_value
2287
+
2288
+ # Initialize silence duration (will be updated by external tracking)
2289
+ G.nodes[node]["silence_duration"] = 0.0
2290
+
2291
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
2292
+ """Validate SHA-specific preconditions."""
2293
+ from .preconditions import validate_silence
2294
+
2295
+ validate_silence(G, node)
2296
+
2297
+ def _collect_metrics(
2298
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
2299
+ ) -> dict[str, Any]:
2300
+ """Collect SHA-specific metrics."""
2301
+ from .metrics import silence_metrics
2302
+
2303
+ return silence_metrics(G, node, state_before["vf"], state_before["epi"])
2304
+
2305
+
2306
+ @register_operator
2307
+ class Expansion(Operator):
2308
+ """Expansion structural operator (VAL) - Structural dilation for exploration.
2309
+
2310
+ Activates glyph ``VAL`` to dilate the node's structure, unfolding neighbouring
2311
+ trajectories and extending operational boundaries to explore additional coherence volume.
2312
+
2313
+ TNFR Context: Expansion increases EPI magnitude and νf, enabling exploration of new
2314
+ structural configurations while maintaining core identity. VAL embodies fractality -
2315
+ structures scale while preserving their essential form.
2316
+
2317
+ Use Cases: Growth processes (biological, cognitive, organizational), exploration phases,
2318
+ capacity building, network extension.
2319
+
2320
+ Typical Sequences: VAL → IL (expand then stabilize), OZ → VAL (dissonance enables
2321
+ expansion), VAL → THOL (expansion triggers reorganization).
2322
+
2323
+ Avoid: VAL → NUL (contradictory), multiple consecutive VAL without consolidation.
2324
+
2325
+ Examples
2326
+ --------
2327
+ >>> from tnfr.constants import EPI_PRIMARY, VF_PRIMARY
2328
+ >>> from tnfr.dynamics import set_delta_nfr_hook
2329
+ >>> from tnfr.structural import create_nfr, run_sequence
2330
+ >>> from tnfr.operators.definitions import Expansion
2331
+ >>> G, node = create_nfr("theta", epi=0.47, vf=0.95)
2332
+ >>> spreads = iter([(0.06, 0.08)])
2333
+ >>> def open_volume(graph):
2334
+ ... d_epi, d_vf = next(spreads)
2335
+ ... graph.nodes[node][EPI_PRIMARY] += d_epi
2336
+ ... graph.nodes[node][VF_PRIMARY] += d_vf
2337
+ >>> set_delta_nfr_hook(G, open_volume)
2338
+ >>> run_sequence(G, node, [Expansion()])
2339
+ >>> round(G.nodes[node][EPI_PRIMARY], 2)
2340
+ 0.53
2341
+ >>> round(G.nodes[node][VF_PRIMARY], 2)
2342
+ 1.03
2343
+
2344
+ **Biomedical**: Growth, tissue expansion, neural network development
2345
+ **Cognitive**: Knowledge domain expansion, conceptual broadening
2346
+ **Social**: Team scaling, market expansion, network growth
2347
+ """
2348
+
2349
+ __slots__ = ()
2350
+ name: ClassVar[str] = EXPANSION
2351
+ glyph: ClassVar[Glyph] = Glyph.VAL
2352
+
2353
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
2354
+ """Validate VAL-specific preconditions."""
2355
+ from .preconditions import validate_expansion
2356
+
2357
+ validate_expansion(G, node)
2358
+
2359
+ def _collect_metrics(
2360
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
2361
+ ) -> dict[str, Any]:
2362
+ """Collect VAL-specific metrics."""
2363
+ from .metrics import expansion_metrics
2364
+
2365
+ return expansion_metrics(G, node, state_before["vf"], state_before["epi"])
2366
+
2367
+
2368
+ @register_operator
2369
+ class Contraction(Operator):
2370
+ """Contraction structural operator (NUL) - Structural concentration and densification.
2371
+
2372
+ Activates glyph ``NUL`` to concentrate the node's structure, pulling peripheral
2373
+ trajectories back into the core EPI to tighten coherence gradients.
2374
+
2375
+ TNFR Context
2376
+ ------------
2377
+ Contraction (NUL) embodies harmonic contraction - the complementary principle to
2378
+ expansion (VAL). When structure contracts (W → W' where W' = W × λ, λ < 1), it
2379
+ doesn't simply shrink; it undergoes **densification**: the structural pressure
2380
+ concentrates, amplifying ΔNFR while reducing volume.
2381
+
2382
+ **Key Elements:**
2383
+
2384
+ - **Harmonic Contraction**: Volume reduction W → W × λ (default λ = 0.85)
2385
+ - **Density Amplification**: ΔNFR → ΔNFR × ρ (default ρ = 1.35)
2386
+ - **Structural Pressure**: Product νf × ΔNFR slightly increases (~1.15x)
2387
+ - **Core Strengthening**: Peripheral trajectories fold into coherent center
2388
+ - **Complementary to VAL**: Enables expand-contract cycles for exploration-consolidation
2389
+
2390
+ **Canonical Densification:**
2391
+
2392
+ - Volume contraction: V' = V × NUL_scale (default 0.85)
2393
+ - Density amplification: ΔNFR' = ΔNFR × NUL_densification_factor (default 1.35)
2394
+ - Product effect: νf × ΔNFR ≈ 0.85 × 1.35 ≈ 1.15 (slight structural pressure increase)
2395
+ - Equilibrium preservation: ΔNFR = 0 remains 0
2396
+ - Sign preservation: Negative ΔNFR amplifies correctly (intensified contraction)
2397
+
2398
+ **Relationship to Nodal Equation:**
2399
+
2400
+ The nodal equation ∂EPI/∂t = νf · ΔNFR(t) remains valid through NUL application.
2401
+ While νf decreases (reorganization rate slows), ΔNFR increases (pressure concentrates),
2402
+ keeping the product bounded. This preserves structural integrity during contraction.
2403
+
2404
+ **Role in VAL ↔ NUL Cycles:**
2405
+
2406
+ NUL is the complementary operator to VAL (Expansion), enabling rhythmic cycles of
2407
+ exploration and consolidation. VAL → NUL → IL sequences are fundamental to TNFR
2408
+ dynamics: expand to explore, contract to consolidate, stabilize to preserve.
2409
+
2410
+ Use Cases
2411
+ ---------
2412
+ **Biomedical**:
2413
+
2414
+ - **Apoptosis**: Programmed cell death (controlled elimination)
2415
+ - **Wound Healing**: Tissue contraction closing wound gaps
2416
+ - **Neural Pruning**: Synaptic elimination strengthening key pathways
2417
+ - **Muscle Contraction**: Coordinated fiber shortening for movement
2418
+
2419
+ **Cognitive**:
2420
+
2421
+ - **Focus Intensification**: Attention narrowing to essential elements
2422
+ - **Concept Refinement**: Simplifying complex ideas to core principles
2423
+ - **Mental Compression**: "Less is more" - removing cognitive clutter
2424
+ - **Memory Consolidation**: Compressing experiences into dense representations
2425
+
2426
+ **Social**:
2427
+
2428
+ - **Team Downsizing**: Strategic workforce reduction to core competencies
2429
+ - **Resource Consolidation**: Pooling distributed resources for efficiency
2430
+ - **Core Competency Focus**: Eliminating peripheral activities
2431
+ - **Crisis Response**: Defensive contraction under external pressure
2432
+
2433
+ Typical Sequences
2434
+ ---------------------------
2435
+ **Valid Patterns:**
2436
+
2437
+ - **NUL → IL**: Contract then stabilize (safe consolidation)
2438
+ - **VAL → NUL → IL**: Expand-contract-stabilize cycle (exploration-consolidation)
2439
+ - **THOL → NUL**: Self-organize then refine (emergent structure consolidation)
2440
+ - **OZ → NUL**: Dissonance followed by compression (pressure intensification)
2441
+ - **NUL → SHA**: Compress then silence (preservation through contraction)
2442
+ - **EN → NUL → IL**: Receive, compress, stabilize (efficient integration)
2443
+
2444
+ **Avoid Patterns:**
2445
+
2446
+ - **NUL → VAL**: Contradictory (immediate reversal wastes structural energy)
2447
+ - **NUL → NUL**: Over-compression risk (may trigger structural collapse)
2448
+ - **NUL → OZ**: Compression + dissonance = dangerous instability
2449
+ - **Excessive NUL**: Multiple contractions without stabilization (fragmentation risk)
2450
+
2451
+ Preconditions
2452
+ -------------
2453
+ - Node must have adequate EPI baseline (cannot contract from near-zero)
2454
+ - ΔNFR should be present (though densification amplifies it)
2455
+ - Sufficient structural integrity to withstand compression
2456
+
2457
+ Structural Effects
2458
+ ------------------
2459
+ - **EPI**: Decreases (volume reduction)
2460
+ - **νf**: Decreases (reorganization rate slows)
2461
+ - **ΔNFR**: Increases (densification - primary effect)
2462
+ - **C(t)**: May increase locally (tighter coherence gradients)
2463
+ - **Product νf × ΔNFR**: Slight increase (~1.15x)
2464
+
2465
+ Metrics
2466
+ -----------------
2467
+ - Volume reduction: EPI change ratio
2468
+ - Densification factor: ΔNFR amplification
2469
+ - Frequency decrease: νf reduction
2470
+ - Structural pressure: Product νf × ΔNFR
2471
+
2472
+ Compatibility
2473
+ ---------------------
2474
+ **Compatible with**: IL (stabilization), SHA (preservation), THOL (organization),
2475
+ EN (reception before contraction)
2476
+
2477
+ **Complementary with**: VAL (expansion) - enables rhythmic cycles
2478
+
2479
+ **Avoid with**: OZ (dissonance), consecutive NUL (over-compression)
2480
+
2481
+ **Natural progressions**: NUL typically followed by IL (stabilization) or SHA
2482
+ (preservation) to seal contracted form
2483
+
2484
+ Warnings
2485
+ --------
2486
+ **Over-compression Risks:**
2487
+
2488
+ - **Structural Collapse**: Excessive contraction can fragment coherence
2489
+ - **Loss of Degrees of Freedom**: Irreversible elimination of structural dimensions
2490
+ - **Requires Adequate Baseline**: Cannot contract from EPI ≈ 0 (no structure to compress)
2491
+ - **Irreversibility**: Cannot reverse without VAL (expansion) - contraction loses information
2492
+
2493
+ **Collapse Conditions:**
2494
+
2495
+ - Multiple consecutive NUL without stabilization (IL)
2496
+ - Contraction when EPI already critically low
2497
+ - NUL → OZ sequences (compression + instability)
2498
+ - Insufficient network coupling to maintain identity
2499
+
2500
+ **Safe Usage:**
2501
+
2502
+ - Always follow with IL (Coherence) or SHA (Silence)
2503
+ - Ensure adequate EPI baseline before contraction
2504
+ - Use VAL → NUL cycles rather than isolated NUL
2505
+ - Monitor C(t) to detect fragmentation
2506
+
2507
+ Comparison with Complementary Operators
2508
+ ---------------------------------------
2509
+ **NUL vs. VAL (Expansion)**:
2510
+
2511
+ - NUL contracts volume, VAL expands it
2512
+ - NUL increases ΔNFR density, VAL distributes it
2513
+ - NUL consolidates, VAL explores
2514
+ - Together enable expand-contract rhythms
2515
+
2516
+ **NUL vs. IL (Coherence)**:
2517
+
2518
+ - NUL compresses structure, IL stabilizes it
2519
+ - NUL increases ΔNFR (densification), IL reduces it (stabilization)
2520
+ - NUL changes geometry, IL preserves it
2521
+ - Often used in sequence: NUL → IL
2522
+
2523
+ **NUL vs. THOL (Self-organization)**:
2524
+
2525
+ - NUL simplifies structure, THOL complexifies it
2526
+ - NUL reduces dimensions, THOL creates sub-EPIs
2527
+ - NUL consolidates, THOL differentiates
2528
+ - Can work sequentially: THOL → NUL (organize then refine)
2529
+
2530
+ Examples
2531
+ --------
2532
+ **Technical Example:**
2533
+
2534
+ >>> from tnfr.constants import DNFR_PRIMARY, EPI_PRIMARY, VF_PRIMARY
2535
+ >>> from tnfr.operators import apply_glyph
2536
+ >>> from tnfr.types import Glyph
2537
+ >>> from tnfr.structural import create_nfr
2538
+ >>> G, node = create_nfr("iota", epi=0.5, vf=1.0)
2539
+ >>> G.nodes[node][DNFR_PRIMARY] = 0.1
2540
+ >>> # Apply NUL via canonical glyph application
2541
+ >>> apply_glyph(G, node, Glyph.NUL)
2542
+ >>> # Verify densification: ΔNFR increased despite contraction
2543
+ >>> G.nodes[node][DNFR_PRIMARY] > 0.1 # doctest: +SKIP
2544
+ True
2545
+ >>> # Check telemetry for densification event
2546
+ >>> 'nul_densification_log' in G.graph # doctest: +SKIP
2547
+ True
2548
+
2549
+ **Example 1: Neural Pruning**
2550
+
2551
+ >>> # Brain eliminates weak synaptic connections
2552
+ >>> G_brain, synapse = create_nfr("neural_connection", epi=0.39, vf=1.05)
2553
+ >>> # Synapse has weak activity pattern
2554
+ >>> G_brain.nodes[synapse][DNFR_PRIMARY] = 0.05
2555
+ >>> # Apply NUL to eliminate weak connection
2556
+ >>> from tnfr.structural import run_sequence
2557
+ >>> from tnfr.operators.definitions import Contraction, Coherence
2558
+ >>> run_sequence(G_brain, synapse, [Contraction(), Coherence()])
2559
+ >>> # Result: Synapse contracts, neural network becomes more efficient
2560
+ >>> # Remaining connections are strengthened through consolidation
2561
+
2562
+ **Example 2: Strategic Focus**
2563
+
2564
+ >>> # Company eliminates peripheral business units
2565
+ >>> G_company, strategy = create_nfr("business_model", epi=0.42, vf=1.00)
2566
+ >>> # Company has diffuse strategy with many weak initiatives
2567
+ >>> G_company.nodes[strategy][DNFR_PRIMARY] = 0.08
2568
+ >>> # Apply NUL to focus on core competencies
2569
+ >>> run_sequence(G_company, strategy, [Contraction(), Coherence()])
2570
+ >>> # Result: Strategy contracts to core, peripheral units eliminated
2571
+ >>> # Core competencies receive concentrated resources
2572
+
2573
+ **Example 3: Expand-Contract Cycle**
2574
+
2575
+ >>> # Learning cycle: explore broadly then consolidate
2576
+ >>> from tnfr.operators.definitions import Expansion
2577
+ >>> G_learning, concept = create_nfr("understanding", epi=0.35, vf=0.95)
2578
+ >>> G_learning.nodes[concept][DNFR_PRIMARY] = 0.06
2579
+ >>> # VAL → NUL → IL: Expand → Contract → Stabilize
2580
+ >>> run_sequence(G_learning, concept, [Expansion(), Contraction(), Coherence()])
2581
+ >>> # Result: Exploration phase (VAL) followed by consolidation (NUL)
2582
+ >>> # Final understanding is both broad (from VAL) and coherent (from NUL → IL)
2583
+
2584
+ **Example 4: Memory Consolidation**
2585
+
2586
+ >>> # Brain compresses daily experiences into dense memories
2587
+ >>> G_memory, experience = create_nfr("daily_events", epi=0.55, vf=1.10)
2588
+ >>> # Many experiences need compression for long-term storage
2589
+ >>> G_memory.nodes[experience][DNFR_PRIMARY] = 0.12
2590
+ >>> # NUL → SHA: Compress then preserve (sleep consolidation)
2591
+ >>> from tnfr.operators.definitions import Silence
2592
+ >>> run_sequence(G_memory, experience, [Contraction(), Silence()])
2593
+ >>> # Result: Experiences compressed into efficient representations
2594
+ >>> # Preserved in stable form for later retrieval
2595
+
2596
+ See Also
2597
+ --------
2598
+ Expansion : Complementary operator enabling expand-contract cycles
2599
+ Coherence : Stabilizes contracted structure (NUL → IL pattern)
2600
+ SelfOrganization : Can follow contraction (THOL → NUL refinement)
2601
+ """
2602
+
2603
+ __slots__ = ()
2604
+ name: ClassVar[str] = CONTRACTION
2605
+ glyph: ClassVar[Glyph] = Glyph.NUL
2606
+
2607
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
2608
+ """Validate NUL-specific preconditions."""
2609
+ from .preconditions import validate_contraction
2610
+
2611
+ validate_contraction(G, node)
2612
+
2613
+ def _collect_metrics(
2614
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
2615
+ ) -> dict[str, Any]:
2616
+ """Collect NUL-specific metrics."""
2617
+ from .metrics import contraction_metrics
2618
+
2619
+ return contraction_metrics(G, node, state_before["vf"], state_before["epi"])
2620
+
2621
+
2622
+ @register_operator
2623
+ class SelfOrganization(Operator):
2624
+ """Self-Organization structural operator (THOL) - Autonomous emergent reorganization.
2625
+
2626
+ Activates glyph ``THOL`` to spawn nested EPIs and trigger self-organizing cascades
2627
+ within the local structure, enabling autonomous coherent reorganization.
2628
+
2629
+ TNFR Context: Self-organization (THOL) embodies emergence - when ∂²EPI/∂t² > τ, the
2630
+ system bifurcates and generates new sub-EPIs that organize coherently without external
2631
+ direction. THOL is the engine of complexity and novelty in TNFR. This is not just
2632
+ autoorganization but **structural metabolism**: T'HOL reorganizes experience into
2633
+ structure without external instruction.
2634
+
2635
+ **Canonical Characteristics:**
2636
+
2637
+ - **Bifurcation nodal**: When ∂²EPI/∂t² > τ, spawns new sub-EPIs
2638
+ - **Autonomous reorganization**: No external control, self-directed
2639
+ - **Vibrational metabolism**: Digests external experience into internal structure
2640
+ - **Complexity emergence**: Engine of novelty and evolution in TNFR
2641
+
2642
+ **Vibrational Metabolism (Canonical THOL):**
2643
+
2644
+ THOL implements the metabolic principle: capturing network vibrational signals
2645
+ (EPI gradients, phase variance) and transforming them into internal structure
2646
+ (sub-EPIs). This ensures that bifurcation reflects not only internal acceleration
2647
+ but also the network's coherence field.
2648
+
2649
+ Metabolic formula: ``sub-EPI = base + gradient*w₁ + variance*w₂``
2650
+
2651
+ - If node has neighbors: Captures and metabolizes network signals
2652
+ - If node is isolated: Falls back to pure internal bifurcation
2653
+ - Configurable via ``THOL_METABOLIC_ENABLED`` and weight parameters
2654
+
2655
+ Use Cases: Emergence processes, bifurcation events, creative reorganization, complex
2656
+ system evolution, spontaneous order generation.
2657
+
2658
+ Typical Sequences: OZ → THOL (dissonance catalyzes emergence), THOL → RA (emergent
2659
+ forms propagate), THOL → IL (organize then stabilize), EN → THOL (reception triggers
2660
+ reorganization).
2661
+
2662
+ Critical: THOL requires sufficient ΔNFR and network connectivity for bifurcation.
2663
+
2664
+ Examples
2665
+ --------
2666
+ >>> from tnfr.constants import EPI_PRIMARY, VF_PRIMARY
2667
+ >>> from tnfr.dynamics import set_delta_nfr_hook
2668
+ >>> from tnfr.structural import create_nfr, run_sequence
2669
+ >>> from tnfr.operators.definitions import SelfOrganization
2670
+ >>> G, node = create_nfr("kappa", epi=0.66, vf=1.10)
2671
+ >>> cascades = iter([(0.04, 0.05)])
2672
+ >>> def spawn(graph):
2673
+ ... d_epi, d_vf = next(cascades)
2674
+ ... graph.nodes[node][EPI_PRIMARY] += d_epi
2675
+ ... graph.nodes[node][VF_PRIMARY] += d_vf
2676
+ ... graph.graph.setdefault("sub_epi", []).append(round(graph.nodes[node][EPI_PRIMARY], 2))
2677
+ >>> set_delta_nfr_hook(G, spawn)
2678
+ >>> run_sequence(G, node, [SelfOrganization()])
2679
+ >>> G.graph["sub_epi"]
2680
+ [0.7]
2681
+
2682
+ **Biomedical**: Embryogenesis, immune response, neural plasticity, wound healing
2683
+ **Cognitive**: Insight generation, creative breakthroughs, paradigm shifts
2684
+ **Social**: Innovation emergence, cultural evolution, spontaneous movements
2685
+ """
2686
+
2687
+ __slots__ = ()
2688
+ name: ClassVar[str] = SELF_ORGANIZATION
2689
+ glyph: ClassVar[Glyph] = Glyph.THOL
2690
+
2691
+ def __call__(self, G: TNFRGraph, node: Any, **kw: Any) -> None:
2692
+ """Apply T'HOL with bifurcation logic.
2693
+
2694
+ If ∂²EPI/∂t² > τ, generates sub-EPIs through bifurcation.
2695
+
2696
+ Parameters
2697
+ ----------
2698
+ G : TNFRGraph
2699
+ Graph storing TNFR nodes
2700
+ node : Any
2701
+ Target node identifier
2702
+ **kw : Any
2703
+ Additional parameters including:
2704
+ - tau: Bifurcation threshold (default from graph config or 0.1)
2705
+ - validate_preconditions: Enable precondition checks (default True)
2706
+ - collect_metrics: Enable metrics collection (default False)
2707
+ """
2708
+ # Compute structural acceleration before base operator
2709
+ d2_epi = self._compute_epi_acceleration(G, node)
2710
+
2711
+ # Get bifurcation threshold (tau) from kwargs or graph config
2712
+ tau = kw.get("tau")
2713
+ if tau is None:
2714
+ tau = float(G.graph.get("THOL_BIFURCATION_THRESHOLD", 0.1))
2715
+
2716
+ # Apply base operator (includes glyph application and metrics)
2717
+ super().__call__(G, node, **kw)
2718
+
2719
+ # Bifurcate if acceleration exceeds threshold
2720
+ if d2_epi > tau:
2721
+ # Validate depth before bifurcation
2722
+ self._validate_bifurcation_depth(G, node)
2723
+ self._spawn_sub_epi(G, node, d2_epi=d2_epi, tau=tau)
2724
+
2725
+ # CANONICAL VALIDATION: Verify collective coherence of sub-EPIs
2726
+ # When THOL creates multiple sub-EPIs, they must form a coherent ensemble
2727
+ # that preserves the structural identity of the parent node (TNFR Manual §2.2.10)
2728
+ # Always validate if node has sub-EPIs (whether created now or previously)
2729
+ if G.nodes[node].get("sub_epis"):
2730
+ self._validate_collective_coherence(G, node)
2731
+
2732
+ def _compute_epi_acceleration(self, G: TNFRGraph, node: Any) -> float:
2733
+ """Calculate ∂²EPI/∂t² from node's EPI history.
2734
+
2735
+ Uses finite difference approximation:
2736
+ d²EPI/dt² ≈ (EPI_t - 2*EPI_{t-1} + EPI_{t-2}) / (Δt)²
2737
+ For unit time steps: d²EPI/dt² ≈ EPI_t - 2*EPI_{t-1} + EPI_{t-2}
2738
+
2739
+ Parameters
2740
+ ----------
2741
+ G : TNFRGraph
2742
+ Graph containing the node
2743
+ node : Any
2744
+ Node identifier
2745
+
2746
+ Returns
2747
+ -------
2748
+ float
2749
+ Magnitude of EPI acceleration (always non-negative)
2750
+ """
2751
+ from ..alias import get_attr
2752
+ from ..constants.aliases import ALIAS_EPI
2753
+
2754
+ # Get EPI history (maintained by node for temporal analysis)
2755
+ history = G.nodes[node].get("epi_history", [])
2756
+
2757
+ # Need at least 3 points for second derivative
2758
+ if len(history) < 3:
2759
+ return 0.0
2760
+
2761
+ # Finite difference: d²EPI/dt² ≈ (EPI_t - 2*EPI_{t-1} + EPI_{t-2})
2762
+ epi_t = float(history[-1])
2763
+ epi_t1 = float(history[-2])
2764
+ epi_t2 = float(history[-3])
2765
+
2766
+ d2_epi = epi_t - 2.0 * epi_t1 + epi_t2
2767
+
2768
+ return abs(d2_epi)
2769
+
2770
+ def _spawn_sub_epi(
2771
+ self, G: TNFRGraph, node: Any, d2_epi: float, tau: float
2772
+ ) -> None:
2773
+ """Generate sub-EPI through bifurcation with vibrational metabolism.
2774
+
2775
+ When acceleration exceeds threshold, creates nested sub-structure that:
2776
+ 1. Captures network vibrational signals (metabolic perception)
2777
+ 2. Metabolizes signals into sub-EPI magnitude (digestion)
2778
+ 3. Inherits properties from parent while integrating field context
2779
+
2780
+ This implements canonical THOL: "reorganizes external experience into
2781
+ internal structure without external instruction".
2782
+
2783
+ ARCHITECTURAL: Sub-EPIs are created as independent NFR nodes to enable
2784
+ operational fractality - recursive operator application, hierarchical metrics,
2785
+ and multi-level bifurcation.
2786
+
2787
+ Parameters
2788
+ ----------
2789
+ G : TNFRGraph
2790
+ Graph containing the node
2791
+ node : Any
2792
+ Node identifier
2793
+ d2_epi : float
2794
+ Current EPI acceleration
2795
+ tau : float
2796
+ Bifurcation threshold that was exceeded
2797
+ """
2798
+ from ..alias import get_attr, set_attr
2799
+ from ..constants.aliases import ALIAS_EPI, ALIAS_VF, ALIAS_THETA
2800
+ from .metabolism import capture_network_signals, metabolize_signals_into_subepi
2801
+
2802
+ # Get current node state
2803
+ parent_epi = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
2804
+ parent_vf = float(get_attr(G.nodes[node], ALIAS_VF, 1.0))
2805
+ parent_theta = float(get_attr(G.nodes[node], ALIAS_THETA, 0.0))
2806
+
2807
+ # Check if vibrational metabolism is enabled
2808
+ metabolic_enabled = G.graph.get("THOL_METABOLIC_ENABLED", True)
2809
+
2810
+ # CANONICAL METABOLISM: Capture network context
2811
+ network_signals = None
2812
+ if metabolic_enabled:
2813
+ network_signals = capture_network_signals(G, node)
2814
+
2815
+ # Get metabolic weights from graph config
2816
+ gradient_weight = float(G.graph.get("THOL_METABOLIC_GRADIENT_WEIGHT", 0.15))
2817
+ complexity_weight = float(G.graph.get("THOL_METABOLIC_COMPLEXITY_WEIGHT", 0.10))
2818
+
2819
+ # CANONICAL METABOLISM: Digest signals into sub-EPI
2820
+ sub_epi_value = metabolize_signals_into_subepi(
2821
+ parent_epi=parent_epi,
2822
+ signals=network_signals if metabolic_enabled else None,
2823
+ d2_epi=d2_epi,
2824
+ scaling_factor=_THOL_SUB_EPI_SCALING,
2825
+ gradient_weight=gradient_weight,
2826
+ complexity_weight=complexity_weight,
2827
+ )
2828
+
2829
+ # Get current timestamp from glyph history length
2830
+ timestamp = len(G.nodes[node].get("glyph_history", []))
2831
+
2832
+ # Determine parent bifurcation level for hierarchical telemetry
2833
+ parent_level = G.nodes[node].get("_bifurcation_level", 0)
2834
+ child_level = parent_level + 1
2835
+
2836
+ # Construct hierarchy path for full traceability
2837
+ parent_path = G.nodes[node].get("_hierarchy_path", [])
2838
+ child_path = parent_path + [node]
2839
+
2840
+ # ARCHITECTURAL: Create sub-EPI as independent NFR node
2841
+ # This enables operational fractality - recursive operators, hierarchical metrics
2842
+ sub_node_id = self._create_sub_node(
2843
+ G,
2844
+ parent_node=node,
2845
+ sub_epi=sub_epi_value,
2846
+ parent_vf=parent_vf,
2847
+ parent_theta=parent_theta,
2848
+ child_level=child_level,
2849
+ child_path=child_path,
2850
+ )
2851
+
2852
+ # Store sub-EPI metadata for telemetry and backward compatibility
2853
+ sub_epi_record = {
2854
+ "epi": sub_epi_value,
2855
+ "vf": parent_vf,
2856
+ "timestamp": timestamp,
2857
+ "d2_epi": d2_epi,
2858
+ "tau": tau,
2859
+ "node_id": sub_node_id, # Reference to independent node
2860
+ "metabolized": network_signals is not None and metabolic_enabled,
2861
+ "network_signals": network_signals,
2862
+ "bifurcation_level": child_level, # Hierarchical depth tracking
2863
+ "hierarchy_path": child_path, # Full parent chain for traceability
2864
+ }
2865
+
2866
+ # Keep metadata list for telemetry/metrics backward compatibility
2867
+ sub_epis = G.nodes[node].get("sub_epis", [])
2868
+ sub_epis.append(sub_epi_record)
2869
+ G.nodes[node]["sub_epis"] = sub_epis
2870
+
2871
+ # Increment parent EPI using canonical emergence contribution
2872
+ # This reflects that bifurcation increases total structural complexity
2873
+ new_epi = parent_epi + sub_epi_value * _THOL_EMERGENCE_CONTRIBUTION
2874
+ set_attr(G.nodes[node], ALIAS_EPI, new_epi)
2875
+
2876
+ # CANONICAL PROPAGATION: Enable network cascade dynamics
2877
+ if G.graph.get("THOL_PROPAGATION_ENABLED", True):
2878
+ from .metabolism import propagate_subepi_to_network
2879
+
2880
+ propagations = propagate_subepi_to_network(G, node, sub_epi_record)
2881
+
2882
+ # Record propagation telemetry for cascade analysis
2883
+ if propagations:
2884
+ G.graph.setdefault("thol_propagations", []).append(
2885
+ {
2886
+ "source_node": node,
2887
+ "sub_epi": sub_epi_value,
2888
+ "propagations": propagations,
2889
+ "timestamp": timestamp,
2890
+ }
2891
+ )
2892
+
2893
+ def _create_sub_node(
2894
+ self,
2895
+ G: TNFRGraph,
2896
+ parent_node: Any,
2897
+ sub_epi: float,
2898
+ parent_vf: float,
2899
+ parent_theta: float,
2900
+ child_level: int,
2901
+ child_path: list,
2902
+ ) -> str:
2903
+ """Create sub-EPI as independent NFR node for operational fractality.
2904
+
2905
+ Sub-nodes are full TNFR nodes that can have operators applied, bifurcate
2906
+ recursively, and contribute to hierarchical metrics.
2907
+
2908
+ Parameters
2909
+ ----------
2910
+ G : TNFRGraph
2911
+ Graph containing the parent node
2912
+ parent_node : Any
2913
+ Parent node identifier
2914
+ sub_epi : float
2915
+ EPI value for the sub-node
2916
+ parent_vf : float
2917
+ Parent's structural frequency (inherited with damping)
2918
+ parent_theta : float
2919
+ Parent's phase (inherited)
2920
+ child_level : int
2921
+ Bifurcation level for hierarchical tracking
2922
+ child_path : list
2923
+ Full hierarchy path (ancestor chain)
2924
+
2925
+ Returns
2926
+ -------
2927
+ str
2928
+ Identifier of the newly created sub-node
2929
+ """
2930
+ from ..constants import EPI_PRIMARY, VF_PRIMARY, THETA_PRIMARY, DNFR_PRIMARY
2931
+ from ..dynamics import set_delta_nfr_hook
2932
+
2933
+ # Generate unique sub-node ID
2934
+ sub_nodes_list = G.nodes[parent_node].get("sub_nodes", [])
2935
+ sub_index = len(sub_nodes_list)
2936
+ sub_node_id = f"{parent_node}_sub_{sub_index}"
2937
+
2938
+ # Get parent hierarchy level
2939
+ parent_hierarchy_level = G.nodes[parent_node].get("hierarchy_level", 0)
2940
+
2941
+ # Inherit parent's vf with slight damping (canonical: 95%)
2942
+ sub_vf = parent_vf * 0.95
2943
+
2944
+ # Create the sub-node with full TNFR state
2945
+ G.add_node(
2946
+ sub_node_id,
2947
+ **{
2948
+ EPI_PRIMARY: float(sub_epi),
2949
+ VF_PRIMARY: float(sub_vf),
2950
+ THETA_PRIMARY: float(parent_theta),
2951
+ DNFR_PRIMARY: 0.0,
2952
+ "parent_node": parent_node,
2953
+ "hierarchy_level": parent_hierarchy_level + 1,
2954
+ "_bifurcation_level": child_level, # Hierarchical depth tracking
2955
+ "_hierarchy_path": child_path, # Full ancestor chain
2956
+ "epi_history": [
2957
+ float(sub_epi)
2958
+ ], # Initialize history for future bifurcation
2959
+ "glyph_history": [],
2960
+ },
2961
+ )
2962
+
2963
+ # Ensure ΔNFR hook is set for the sub-node
2964
+ # (inherits from graph-level hook, but ensure it's activated)
2965
+ if hasattr(G, "graph") and "_delta_nfr_hook" in G.graph:
2966
+ # Hook already set at graph level, will apply to sub-node automatically
2967
+ pass
2968
+
2969
+ # Track sub-node in parent
2970
+ sub_nodes_list.append(sub_node_id)
2971
+ G.nodes[parent_node]["sub_nodes"] = sub_nodes_list
2972
+
2973
+ # Track hierarchy in graph metadata
2974
+ hierarchy = G.graph.setdefault("hierarchy", {})
2975
+ hierarchy.setdefault(parent_node, []).append(sub_node_id)
2976
+
2977
+ return sub_node_id
2978
+
2979
+ def _validate_bifurcation_depth(self, G: TNFRGraph, node: Any) -> None:
2980
+ """Validate bifurcation depth before creating new sub-EPI.
2981
+
2982
+ Checks if the current bifurcation level is at or exceeds the configured
2983
+ maximum depth. Issues a warning if depth limit is reached but still
2984
+ allows the bifurcation (for flexibility in research contexts).
2985
+
2986
+ Parameters
2987
+ ----------
2988
+ G : TNFRGraph
2989
+ Graph containing the node
2990
+ node : Any
2991
+ Node about to undergo bifurcation
2992
+
2993
+ Notes
2994
+ -----
2995
+ TNFR Principle: Deep nesting reflects operational fractality (Invariant #7),
2996
+ but excessive depth may impact performance and interpretability. This
2997
+ validation provides observability without hard constraints.
2998
+
2999
+ The warning allows tracking when hierarchies become complex, enabling
3000
+ researchers to study bifurcation patterns while maintaining system
3001
+ performance awareness.
3002
+ """
3003
+ import logging
3004
+
3005
+ # Get current bifurcation level
3006
+ current_level = G.nodes[node].get("_bifurcation_level", 0)
3007
+
3008
+ # Get max depth from graph config (default: 5 levels)
3009
+ max_depth = int(G.graph.get("THOL_MAX_BIFURCATION_DEPTH", 5))
3010
+
3011
+ # Warn if at or exceeding maximum
3012
+ if current_level >= max_depth:
3013
+ logger = logging.getLogger(__name__)
3014
+ logger.warning(
3015
+ f"Node {node}: Bifurcation depth ({current_level}) at/exceeds "
3016
+ f"maximum ({max_depth}). Deep nesting may impact performance. "
3017
+ f"Consider adjusting THOL_MAX_BIFURCATION_DEPTH if intended."
3018
+ )
3019
+
3020
+ # Record warning in node for telemetry
3021
+ G.nodes[node]["_thol_max_depth_warning"] = True
3022
+
3023
+ # Record event for analysis
3024
+ events = G.graph.setdefault("thol_depth_warnings", [])
3025
+ events.append({
3026
+ "node": node,
3027
+ "depth": current_level,
3028
+ "max_depth": max_depth,
3029
+ })
3030
+
3031
+ def _validate_collective_coherence(self, G: TNFRGraph, node: Any) -> None:
3032
+ """Validate collective coherence of sub-EPI ensemble after bifurcation.
3033
+
3034
+ When THOL creates multiple sub-EPIs, they must form a coherent ensemble
3035
+ that preserves the structural identity of the parent node. This validation
3036
+ ensures the emergent sub-structures maintain structural alignment.
3037
+
3038
+ Parameters
3039
+ ----------
3040
+ G : TNFRGraph
3041
+ Graph containing the node
3042
+ node : Any
3043
+ Node that underwent bifurcation
3044
+
3045
+ Notes
3046
+ -----
3047
+ TNFR Canonical Principle (TNFR Manual §2.2.10):
3048
+ "THOL reorganiza la forma desde dentro, en respuesta a la coherencia
3049
+ vibracional del campo. La autoorganización es resonancia estructurada
3050
+ desde el interior del nodo."
3051
+
3052
+ Implication: Sub-EPIs are not random fragments but coherent structures
3053
+ that emerge from internal resonance.
3054
+
3055
+ This method:
3056
+ 1. Computes collective coherence of sub-EPI ensemble
3057
+ 2. Stores coherence value for telemetry
3058
+ 3. Logs warning if coherence < threshold
3059
+ 4. Records event for analysis
3060
+
3061
+ Does NOT fail the operation - allows monitoring and analysis of
3062
+ low-coherence bifurcations for research purposes.
3063
+ """
3064
+ import logging
3065
+ from .metabolism import compute_subepi_collective_coherence
3066
+
3067
+ # Compute collective coherence
3068
+ coherence = compute_subepi_collective_coherence(G, node)
3069
+
3070
+ # Store for telemetry (always store, even if 0.0 for single/no sub-EPIs)
3071
+ G.nodes[node]["_thol_collective_coherence"] = coherence
3072
+
3073
+ # Get threshold from graph config
3074
+ min_coherence = float(G.graph.get("THOL_MIN_COLLECTIVE_COHERENCE", 0.3))
3075
+
3076
+ # Validate against threshold (only warn if we have multiple sub-EPIs)
3077
+ sub_epis = G.nodes[node].get("sub_epis", [])
3078
+ if len(sub_epis) >= 2 and coherence < min_coherence:
3079
+ # Log warning (but don't fail - allow monitoring)
3080
+ logger = logging.getLogger(__name__)
3081
+ logger.warning(
3082
+ f"Node {node}: THOL collective coherence ({coherence:.3f}) < "
3083
+ f"threshold ({min_coherence}). Sub-EPIs may be fragmenting. "
3084
+ f"Sub-EPI count: {len(sub_epis)}."
3085
+ )
3086
+
3087
+ # Record event for analysis
3088
+ events = G.graph.setdefault("thol_coherence_warnings", [])
3089
+ events.append({
3090
+ "node": node,
3091
+ "coherence": coherence,
3092
+ "threshold": min_coherence,
3093
+ "sub_epi_count": len(sub_epis),
3094
+ })
3095
+
3096
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
3097
+ """Validate THOL-specific preconditions."""
3098
+ from .preconditions import validate_self_organization
3099
+
3100
+ validate_self_organization(G, node)
3101
+
3102
+ def _collect_metrics(
3103
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
3104
+ ) -> dict[str, Any]:
3105
+ """Collect THOL-specific metrics."""
3106
+ from .metrics import self_organization_metrics
3107
+
3108
+ return self_organization_metrics(
3109
+ G, node, state_before["epi"], state_before["vf"]
3110
+ )
3111
+
3112
+
3113
+ @register_operator
3114
+ class Mutation(Operator):
3115
+ """Mutation structural operator (ZHIR) - Controlled phase transformation.
3116
+
3117
+ Activates glyph ``ZHIR`` to recode phase or form, enabling the node to cross
3118
+ structural thresholds and pivot towards a new coherence regime.
3119
+
3120
+ TNFR Context
3121
+ ------------
3122
+ Mutation (ZHIR) implements the fundamental phase transformation mechanism in TNFR:
3123
+ θ → θ' when structural velocity ∂EPI/∂t exceeds threshold ξ. This is NOT random
3124
+ variation but controlled structural transformation that preserves identity (epi_kind)
3125
+ while shifting operational regime. ZHIR enables qualitative state changes without
3126
+ losing coherent structural continuity.
3127
+
3128
+ **Derivation from Nodal Equation**:
3129
+
3130
+ From the nodal equation ∂EPI/∂t = νf · ΔNFR(t), when reorganization pressure builds
3131
+ up (ΔNFR elevated) and transformation capacity exists (νf > 0), structural velocity
3132
+ increases. At threshold crossing (∂EPI/∂t > ξ), the system has sufficient momentum
3133
+ for phase transformation without fragmenting coherence.
3134
+
3135
+ **Key Elements:**
3136
+
3137
+ - **Phase Transformation**: θ → θ' shifts operational regime
3138
+ - **Identity Preservation**: epi_kind maintained through transformation
3139
+ - **Threshold-Controlled**: Requires ∂EPI/∂t > ξ for justification
3140
+ - **Bifurcation Detection**: Monitors ∂²EPI/∂t² for instability
3141
+ - **Grammar U4b**: Requires prior IL and recent destabilizer
3142
+
3143
+ **ZHIR vs Random Mutation**:
3144
+
3145
+ Traditional mutation (biology, evolutionary algorithms) is stochastic variation.
3146
+ TNFR mutation is deterministic reorganization triggered by structural conditions.
3147
+ It's closer to phase transition (ice → water) than genetic mutation.
3148
+
3149
+ **Difference from Bifurcation**:
3150
+
3151
+ - **ZHIR**: Changes phase/regime within single node (qualitative shift)
3152
+ - **Bifurcation**: Creates new sub-EPIs or structural variants (multiplication)
3153
+ - **When ZHIR triggers bifurcation**: High ∂²EPI/∂t² requires THOL for control
3154
+
3155
+ Use Cases
3156
+ ---------
3157
+ **Biomedical**:
3158
+
3159
+ - **Cellular Differentiation**: Stem cell → specialized cell (phase change)
3160
+ - **Metabolic Switching**: Glycolysis → oxidative phosphorylation
3161
+ - **Adaptive Immunity**: Naive T-cell → effector/memory cell
3162
+ - **Epigenetic Changes**: Stress-induced gene expression regime shifts
3163
+ - **Wound Healing Phases**: Inflammation → proliferation → remodeling
3164
+
3165
+ **Cognitive**:
3166
+
3167
+ - **Insight Moments**: Sudden perspective shift (aha! experience)
3168
+ - **Paradigm Transformation**: Fundamental worldview reorganization
3169
+ - **Strategy Changes**: Switching cognitive approach (analytical → intuitive)
3170
+ - **Memory Consolidation**: Working memory → long-term storage
3171
+ - **Belief Revision**: Core assumption restructuring under evidence
3172
+
3173
+ **Social**:
3174
+
3175
+ - **Regime Changes**: Political system transformation (democracy → authoritarianism)
3176
+ - **Cultural Revolutions**: Value system reorganization
3177
+ - **Organizational Transformation**: Hierarchy → network structure
3178
+ - **Disruptive Innovation**: Business model fundamental shift
3179
+ - **Social Movement Crystallization**: Protest → organized movement
3180
+
3181
+ **AI/Computational**:
3182
+
3183
+ - **Mode Switching**: Exploration → exploitation in RL
3184
+ - **Strategy Selection**: Changing between learned policies
3185
+ - **Attention Shifts**: Focus reorientation in transformers
3186
+ - **Learning Regime Change**: Supervised → self-supervised
3187
+ - **Attractor Transition**: Jumping between stable computational states
3188
+
3189
+ Typical Sequences
3190
+ -----------------
3191
+ **Recommended Sequences**:
3192
+
3193
+ - **IL → OZ → ZHIR → IL**: Controlled mutation cycle (stabilize-destabilize-mutate-stabilize)
3194
+ - **AL → IL → OZ → ZHIR → NAV**: Bootstrap with mutation and transition
3195
+ - **THOL → OZ → ZHIR**: Self-organization followed by transformation
3196
+ - **IL → VAL → ZHIR → IL**: Expansion-enabled mutation with consolidation
3197
+ - **OZ → ZHIR → THOL**: Mutation triggering bifurcation (requires THOL handler)
3198
+ - **EN → IL → OZ → ZHIR**: Reception-based mutation (integrate-stabilize-challenge-transform)
3199
+
3200
+ **Sequences to Avoid**:
3201
+
3202
+ - **ZHIR → OZ**: Mutation followed by dissonance = post-transformation instability
3203
+ (violates consolidation principle - transform then destabilize is dangerous)
3204
+ - **ZHIR → ZHIR**: Double mutation without IL = identity fragmentation risk
3205
+ (each mutation needs consolidation before next transformation)
3206
+ - **AL → ZHIR**: Emission directly to mutation = no stable base (violates U4b)
3207
+ (requires IL between emission and mutation for structural foundation)
3208
+ - **ZHIR without closure**: Mutation without SHA/IL/NAV = unconsolidated transformation
3209
+ (grammar U1b requires closure, especially critical after state changes)
3210
+ - **OZ → ZHIR → OZ**: Mutation sandwiched by dissonance = coherence collapse
3211
+ (transformation needs stability, not continued turbulence)
3212
+
3213
+ Preconditions
3214
+ -------------
3215
+ - **Minimum νf**: Structural frequency > 0.05 (ZHIR_MIN_VF) for transformation capacity
3216
+ - **Threshold ξ**: Structural velocity ∂EPI/∂t > 0.1 (ZHIR_THRESHOLD_XI) for justification
3217
+ - **Prior IL**: Stable base required by grammar U4b (ZHIR_REQUIRE_IL_PRECEDENCE)
3218
+ - **Recent destabilizer**: OZ or VAL within ~3 operations (ZHIR_REQUIRE_DESTABILIZER)
3219
+ - **EPI history**: At least 2 points for velocity calculation (ZHIR_MIN_HISTORY_LENGTH)
3220
+ - **Network coupling**: Connected context for phase transformation
3221
+
3222
+ Configuration Parameters
3223
+ ------------------------
3224
+ **Precondition Thresholds**:
3225
+
3226
+ - ``ZHIR_MIN_VF``: Minimum structural frequency (default: 0.05)
3227
+ Node must have sufficient reorganization capacity
3228
+ - ``ZHIR_THRESHOLD_XI``: Mutation threshold ξ for ∂EPI/∂t (default: 0.1)
3229
+ Minimum velocity for justified phase transformation
3230
+ - ``ZHIR_MIN_HISTORY_LENGTH``: EPI history points needed (default: 2)
3231
+ Required for velocity calculation
3232
+
3233
+ **Transformation Parameters**:
3234
+
3235
+ - ``ZHIR_THETA_SHIFT_FACTOR``: Phase shift magnitude (default: 0.3)
3236
+ Controls intensity of phase transformation
3237
+ - ``ZHIR_MUTATION_INTENSITY``: Overall mutation intensity (default: 0.1)
3238
+ Scales transformation effects
3239
+ - ``ZHIR_THETA_SHIFT_DIRECTION``: "auto" (from ΔNFR sign) or "manual"
3240
+ Determines direction of phase shift
3241
+
3242
+ **Bifurcation Detection**:
3243
+
3244
+ - ``BIFURCATION_THRESHOLD_TAU``: Canonical bifurcation threshold τ (default: 0.5)
3245
+ When ∂²EPI/∂t² > τ, bifurcation potential detected
3246
+ - ``ZHIR_BIFURCATION_THRESHOLD``: Legacy threshold (fallback to canonical)
3247
+ - ``ZHIR_BIFURCATION_MODE``: "detection" only (no variant creation)
3248
+
3249
+ **Grammar Validation**:
3250
+
3251
+ - ``ZHIR_STRICT_U4B``: Enforce grammar U4b strictly (default: True)
3252
+ Requires both IL precedence and recent destabilizer
3253
+ - ``ZHIR_REQUIRE_IL_PRECEDENCE``: Require prior IL (default: True)
3254
+ Grammar U4b: stable base needed
3255
+ - ``ZHIR_REQUIRE_DESTABILIZER``: Require recent destabilizer (default: True)
3256
+ Grammar U4b: elevated ΔNFR needed for threshold crossing
3257
+
3258
+ Structural Effects
3259
+ ------------------
3260
+ - **θ (phase)**: Primary effect - transforms to new regime (θ → θ')
3261
+ - **EPI**: May increment during transformation
3262
+ - **ΔNFR**: Typically elevated before ZHIR (from destabilizer)
3263
+ - **νf**: Preserved (transformation capacity maintained)
3264
+ - **epi_kind**: Preserved (identity maintained through transformation)
3265
+ - **Regime**: Changes if phase shift crosses regime boundary
3266
+
3267
+ Metrics
3268
+ -------
3269
+ - ``theta_shift``: Magnitude and direction of phase transformation
3270
+ - ``regime_changed``: Boolean indicating regime boundary crossing
3271
+ - ``depi_dt``: Structural velocity at transformation
3272
+ - ``threshold_met``: Whether ∂EPI/∂t > ξ
3273
+ - ``threshold_ratio``: Velocity to threshold ratio
3274
+ - ``d2_epi``: Structural acceleration (bifurcation detection)
3275
+ - ``bifurcation_potential``: Flag for ∂²EPI/∂t² > τ
3276
+
3277
+ Examples
3278
+ --------
3279
+ **Example 1: Controlled Mutation Cycle**
3280
+
3281
+ >>> from tnfr.structural import create_nfr, run_sequence
3282
+ >>> from tnfr.operators.definitions import Coherence, Dissonance, Mutation
3283
+ >>> from tnfr.metrics import compute_coherence
3284
+ >>>
3285
+ >>> # Create node and establish stable base
3286
+ >>> G, node = create_nfr("system", epi=0.5, vf=1.0, theta=0.2)
3287
+ >>> G.graph["COLLECT_OPERATOR_METRICS"] = True
3288
+ >>>
3289
+ >>> # Canonical mutation sequence: stabilize-destabilize-mutate-stabilize
3290
+ >>> run_sequence(G, node, [
3291
+ ... Coherence(), # IL: Establish stable base (required by U4b)
3292
+ ... Dissonance(), # OZ: Elevate ΔNFR (enables threshold crossing)
3293
+ ... Mutation(), # ZHIR: Transform phase when ∂EPI/∂t > ξ
3294
+ ... Coherence(), # IL: Consolidate new regime
3295
+ ... ])
3296
+ >>>
3297
+ >>> # Analyze transformation
3298
+ >>> metrics = G.graph["operator_metrics"][-2] # ZHIR metrics
3299
+ >>> print(f"Phase transformed: {metrics.get('theta_shift', 0):.3f}")
3300
+ >>> print(f"Regime changed: {metrics.get('regime_changed', False)}")
3301
+ >>> print(f"Threshold met: {metrics.get('threshold_met', False)}")
3302
+ >>> print(f"Coherence maintained: {compute_coherence(G) > 0.6}")
3303
+
3304
+ **Example 2: Bifurcation Detection**
3305
+
3306
+ >>> from tnfr.structural import create_nfr, run_sequence
3307
+ >>> from tnfr.operators.definitions import Coherence, Dissonance, Mutation, SelfOrganization
3308
+ >>>
3309
+ >>> # Create node with accelerating EPI
3310
+ >>> G, node = create_nfr("accelerating", epi=0.4, vf=1.2)
3311
+ >>> # Build acceleration history (high ∂²EPI/∂t²)
3312
+ >>> G.nodes[node]["epi_history"] = [0.1, 0.25, 0.4]
3313
+ >>> G.graph["BIFURCATION_THRESHOLD_TAU"] = 0.3
3314
+ >>>
3315
+ >>> # Apply mutation with bifurcation detection
3316
+ >>> run_sequence(G, node, [Coherence(), Dissonance(), Mutation()])
3317
+ >>>
3318
+ >>> # Check bifurcation detection
3319
+ >>> if G.nodes[node].get("_zhir_bifurcation_potential"):
3320
+ ... print("Bifurcation potential detected - applying THOL for control")
3321
+ ... run_sequence(G, node, [SelfOrganization()])
3322
+
3323
+ **Example 3: Stem Cell Differentiation (Biomedical)**
3324
+
3325
+ >>> from tnfr.structural import create_nfr, run_sequence
3326
+ >>> from tnfr.operators.definitions import Coherence, Dissonance, Mutation
3327
+ >>>
3328
+ >>> # Model stem cell differentiation into specialized cell type
3329
+ >>> G_cell, stem_cell = create_nfr("stem_cell", epi=0.6, vf=1.0, theta=0.0)
3330
+ >>> G_cell.nodes[stem_cell]["cell_type"] = "stem"
3331
+ >>> G_cell.nodes[stem_cell]["differentiation_signals"] = ["growth_factor_X"]
3332
+ >>>
3333
+ >>> # Differentiation sequence
3334
+ >>> run_sequence(G_cell, stem_cell, [
3335
+ ... Coherence(), # IL: Stable pluripotent state
3336
+ ... Dissonance(), # OZ: Differentiation signal received
3337
+ ... Mutation(), # ZHIR: Transform to specialized type
3338
+ ... ])
3339
+ >>>
3340
+ >>> # Cell has transformed phase (regime 0=stem → regime 1=specialized)
3341
+ >>> theta_new = G_cell.nodes[stem_cell]["theta"]
3342
+ >>> # Regime change indicates differentiation completed
3343
+ >>> # Cell maintains identity (is still a cell) but changed operational mode
3344
+
3345
+ **Example 4: Paradigm Shift (Cognitive)**
3346
+
3347
+ >>> from tnfr.structural import create_nfr, run_sequence
3348
+ >>> from tnfr.operators.definitions import Reception, Coherence, Dissonance, Mutation
3349
+ >>>
3350
+ >>> # Scientist encountering evidence that challenges paradigm
3351
+ >>> G_mind, scientist = create_nfr("paradigm", epi=0.7, vf=0.9, theta=0.5)
3352
+ >>> G_mind.nodes[scientist]["paradigm"] = "newtonian"
3353
+ >>>
3354
+ >>> # Paradigm shift sequence
3355
+ >>> run_sequence(G_mind, scientist, [
3356
+ ... Reception(), # EN: Receive anomalous evidence
3357
+ ... Coherence(), # IL: Try to integrate into existing framework
3358
+ ... Dissonance(), # OZ: Evidence creates cognitive dissonance
3359
+ ... Mutation(), # ZHIR: Paradigm shifts to quantum perspective
3360
+ ... ])
3361
+ >>>
3362
+ >>> # Scientist's conceptual framework has transformed
3363
+ >>> # Old paradigm (newtonian) → new paradigm (quantum)
3364
+ >>> # Identity preserved (still the same scientist) but worldview transformed
3365
+
3366
+ **Example 5: Business Model Transformation (Social)**
3367
+
3368
+ >>> from tnfr.structural import create_nfr, run_sequence
3369
+ >>> from tnfr.operators.definitions import Coherence, Dissonance, Mutation, Transition
3370
+ >>>
3371
+ >>> # Company facing market disruption
3372
+ >>> G_org, company = create_nfr("business_model", epi=0.65, vf=0.85, theta=0.3)
3373
+ >>> G_org.nodes[company]["model"] = "traditional_retail"
3374
+ >>>
3375
+ >>> # Business transformation sequence
3376
+ >>> run_sequence(G_org, company, [
3377
+ ... Coherence(), # IL: Current model stable
3378
+ ... Dissonance(), # OZ: Market disruption (e-commerce threat)
3379
+ ... Mutation(), # ZHIR: Transform to digital-first model
3380
+ ... Transition(), # NAV: Navigate to new market position
3381
+ ... ])
3382
+ >>>
3383
+ >>> # Company has transformed operational model
3384
+ >>> # Identity preserved (same company) but strategy fundamentally changed
3385
+
3386
+ Warnings
3387
+ --------
3388
+ - **Identity Loss Risk**: Multiple ZHIR in sequence without IL can cause identity
3389
+ fragmentation. Always consolidate transformations before next mutation.
3390
+
3391
+ - **Requires Consolidation**: ZHIR MUST be followed by IL, NAV, or SHA to stabilize
3392
+ the new regime. Unconsolidated transformations are incoherent.
3393
+
3394
+ - **Grammar U4b Strict**: ZHIR requires prior IL (stable base) AND recent destabilizer
3395
+ (OZ/VAL within ~3 ops). Violations risk unjustified or unstable transformations.
3396
+
3397
+ - **Threshold Critical**: When ∂EPI/∂t < ξ, mutation lacks structural justification.
3398
+ Ensure sufficient ΔNFR elevation (via destabilizer) before ZHIR.
3399
+
3400
+ - **Bifurcation Potential**: When ∂²EPI/∂t² > τ, bifurcation may occur. Must include
3401
+ THOL (handler) or IL (stabilizer) to prevent uncontrolled structural splitting.
3402
+
3403
+ - **Phase Wrapping**: θ is periodic [0, 2π]. Large shifts may wrap around, potentially
3404
+ returning to similar regime. Monitor regime changes, not just phase magnitude.
3405
+
3406
+ Contraindications
3407
+ -----------------
3408
+ - **Do not apply ZHIR without prior IL**: Violates U4b, risks unstable transformation
3409
+ - **Do not apply ZHIR with νf < 0.05**: Insufficient transformation capacity
3410
+ - **Do not apply ZHIR repeatedly**: Each mutation needs IL consolidation between
3411
+ - **Do not apply ZHIR to isolated nodes**: Network context required for regime support
3412
+ - **Do not apply ZHIR after NAV**: Transition already changed regime, redundant mutation
3413
+ - **Do not apply ZHIR with insufficient history**: Need ≥2 EPI points for velocity
3414
+
3415
+ ZHIR vs THOL: Two Types of Transformation
3416
+ ------------------------------------------
3417
+
3418
+ Both ZHIR and THOL are transformers (grammar U4b), but operate differently:
3419
+
3420
+ +-------------------+-------------------------+---------------------------+
3421
+ | Aspect | ZHIR (Mutation) | THOL (Self-organization) |
3422
+ +===================+=========================+===========================+
3423
+ | **Primary effect**| Phase transformation | Sub-EPI creation |
3424
+ | | (θ → θ') | (fractal structuring) |
3425
+ +-------------------+-------------------------+---------------------------+
3426
+ | **Trigger** | ∂EPI/∂t > ξ | ∂²EPI/∂t² > τ |
3427
+ | | (velocity threshold) | (acceleration threshold) |
3428
+ +-------------------+-------------------------+---------------------------+
3429
+ | **Result** | Regime change | Emergent organization |
3430
+ | | (qualitative shift) | (internal complexity) |
3431
+ +-------------------+-------------------------+---------------------------+
3432
+ | **Identity** | Preserved (epi_kind) | Preserved (global form) |
3433
+ +-------------------+-------------------------+---------------------------+
3434
+ | **Structure** | Single node transforms | Creates nested sub-EPIs |
3435
+ +-------------------+-------------------------+---------------------------+
3436
+ | **Grammar role** | Transformer (U4b) | Transformer (U4b) + |
3437
+ | | | Handler (U4a) |
3438
+ +-------------------+-------------------------+---------------------------+
3439
+ | **When to use** | Qualitative state | Internal reorganization |
3440
+ | | change needed | with emergence needed |
3441
+ +-------------------+-------------------------+---------------------------+
3442
+ | **Example** | Cell differentiation | Embryonic development |
3443
+ | | (phase change) | (tissue formation) |
3444
+ +-------------------+-------------------------+---------------------------+
3445
+
3446
+ **Decision Guide**:
3447
+
3448
+ - **Use ZHIR when**: Need phase transition without creating sub-structures
3449
+ (e.g., state machine transition, regime shift, perspective change)
3450
+
3451
+ - **Use THOL when**: Need internal organization with sub-EPIs
3452
+ (e.g., hierarchical emergence, fractal structuring, metabolic capture)
3453
+
3454
+ - **Use both (OZ → ZHIR → THOL)**: When mutation triggers bifurcation
3455
+ (∂²EPI/∂t² > τ after ZHIR), apply THOL to handle structural splitting
3456
+
3457
+ Compatibility
3458
+ -------------
3459
+ **Compatible with**: IL (consolidation), OZ (enabling), NAV (transitioning),
3460
+ THOL (handling bifurcation), SHA (closure)
3461
+
3462
+ **Avoid with**: Multiple consecutive ZHIR, direct AL → ZHIR, ZHIR → OZ sequences
3463
+
3464
+ **Natural progressions**: ZHIR typically preceded by IL+OZ (preparation) and
3465
+ followed by IL/NAV (consolidation) or THOL (bifurcation handling)
3466
+
3467
+ See Also
3468
+ --------
3469
+ Coherence : Stabilizes transformation base and consolidates post-mutation
3470
+ Dissonance : Elevates ΔNFR to enable threshold crossing for mutation
3471
+ SelfOrganization : Handles bifurcation when ZHIR triggers ∂²EPI/∂t² > τ
3472
+ Transition : Navigates between attractor states, complementary to mutation
3473
+
3474
+ References
3475
+ ----------
3476
+ - **AGENTS.md §11 (Mutation)**: Canonical ZHIR definition and physics
3477
+ - **TNFR.pdf §2.2.11**: Theoretical foundation of mutation operator
3478
+ - **UNIFIED_GRAMMAR_RULES.md §U4b**: Transformer context requirements
3479
+ - **ZHIR_BIFURCATION_IMPLEMENTATION.md**: Bifurcation detection details
3480
+ """
3481
+
3482
+ __slots__ = ()
3483
+ name: ClassVar[str] = MUTATION
3484
+ glyph: ClassVar[Glyph] = Glyph.ZHIR
3485
+
3486
+ def __call__(self, G: TNFRGraph, node: Any, **kw: Any) -> None:
3487
+ """Apply ZHIR with bifurcation potential detection and postcondition verification.
3488
+
3489
+ Detects when ∂²EPI/∂t² > τ (bifurcation threshold) and sets telemetry flags
3490
+ to enable validation of grammar U4a. Also verifies postconditions to ensure
3491
+ operator contract fulfillment.
3492
+
3493
+ Parameters
3494
+ ----------
3495
+ G : TNFRGraph
3496
+ Graph storing TNFR nodes
3497
+ node : Any
3498
+ Target node identifier
3499
+ **kw : Any
3500
+ Additional parameters including:
3501
+ - tau: Bifurcation threshold (default from graph config or 0.5)
3502
+ - validate_preconditions: Enable precondition checks (default True)
3503
+ - validate_postconditions: Enable postcondition checks (default False)
3504
+ - collect_metrics: Enable metrics collection (default False)
3505
+ """
3506
+ # Capture state before mutation for postcondition verification
3507
+ validate_postconditions = kw.get("validate_postconditions", False) or G.graph.get(
3508
+ "VALIDATE_OPERATOR_POSTCONDITIONS", False
3509
+ )
3510
+
3511
+ state_before = None
3512
+ if validate_postconditions:
3513
+ state_before = self._capture_state(G, node)
3514
+ # Also capture epi_kind if tracked
3515
+ state_before["epi_kind"] = G.nodes[node].get("epi_kind")
3516
+
3517
+ # Compute structural acceleration before base operator
3518
+ d2_epi = self._compute_epi_acceleration(G, node)
3519
+
3520
+ # Get bifurcation threshold (tau) from kwargs or graph config
3521
+ tau = kw.get("tau")
3522
+ if tau is None:
3523
+ # Try canonical threshold first, then operator-specific, then default
3524
+ tau = float(
3525
+ G.graph.get(
3526
+ "BIFURCATION_THRESHOLD_TAU",
3527
+ G.graph.get("ZHIR_BIFURCATION_THRESHOLD", 0.5),
3528
+ )
3529
+ )
3530
+
3531
+ # Apply base operator (includes glyph application, preconditions, and metrics)
3532
+ super().__call__(G, node, **kw)
3533
+
3534
+ # Detect bifurcation potential if acceleration exceeds threshold
3535
+ if d2_epi > tau:
3536
+ self._detect_bifurcation_potential(G, node, d2_epi=d2_epi, tau=tau)
3537
+
3538
+ # Verify postconditions if enabled
3539
+ if validate_postconditions and state_before is not None:
3540
+ self._verify_postconditions(G, node, state_before)
3541
+
3542
+ def _compute_epi_acceleration(self, G: TNFRGraph, node: Any) -> float:
3543
+ """Calculate ∂²EPI/∂t² from node's EPI history.
3544
+
3545
+ Uses finite difference approximation:
3546
+ d²EPI/dt² ≈ (EPI_t - 2*EPI_{t-1} + EPI_{t-2}) / (Δt)²
3547
+ For unit time steps: d²EPI/dt² ≈ EPI_t - 2*EPI_{t-1} + EPI_{t-2}
3548
+
3549
+ Parameters
3550
+ ----------
3551
+ G : TNFRGraph
3552
+ Graph containing the node
3553
+ node : Any
3554
+ Node identifier
3555
+
3556
+ Returns
3557
+ -------
3558
+ float
3559
+ Magnitude of EPI acceleration (always non-negative)
3560
+ """
3561
+ from ..alias import get_attr
3562
+ from ..constants.aliases import ALIAS_EPI
3563
+
3564
+ # Get EPI history (maintained by node for temporal analysis)
3565
+ history = G.nodes[node].get("epi_history", [])
3566
+
3567
+ # Need at least 3 points for second derivative
3568
+ if len(history) < 3:
3569
+ return 0.0
3570
+
3571
+ # Finite difference: d²EPI/dt² ≈ (EPI_t - 2*EPI_{t-1} + EPI_{t-2})
3572
+ epi_t = float(history[-1])
3573
+ epi_t1 = float(history[-2])
3574
+ epi_t2 = float(history[-3])
3575
+
3576
+ d2_epi = epi_t - 2.0 * epi_t1 + epi_t2
3577
+
3578
+ return abs(d2_epi)
3579
+
3580
+ def _detect_bifurcation_potential(
3581
+ self, G: TNFRGraph, node: Any, d2_epi: float, tau: float
3582
+ ) -> None:
3583
+ """Detect and record bifurcation potential when ∂²EPI/∂t² > τ.
3584
+
3585
+ This implements Option B (conservative detection) from the issue specification.
3586
+ Sets telemetry flags and logs informative message without creating structural
3587
+ variants. Enables validation of grammar U4a requirement.
3588
+
3589
+ Parameters
3590
+ ----------
3591
+ G : TNFRGraph
3592
+ Graph containing the node
3593
+ node : Any
3594
+ Node identifier
3595
+ d2_epi : float
3596
+ Current EPI acceleration
3597
+ tau : float
3598
+ Bifurcation threshold that was exceeded
3599
+ """
3600
+ import logging
3601
+
3602
+ logger = logging.getLogger(__name__)
3603
+
3604
+ # Set telemetry flags for grammar validation
3605
+ G.nodes[node]["_zhir_bifurcation_potential"] = True
3606
+ G.nodes[node]["_zhir_d2epi"] = d2_epi
3607
+ G.nodes[node]["_zhir_tau"] = tau
3608
+
3609
+ # Record bifurcation detection event in graph for analysis
3610
+ bifurcation_events = G.graph.setdefault("zhir_bifurcation_events", [])
3611
+ bifurcation_events.append(
3612
+ {
3613
+ "node": node,
3614
+ "d2_epi": d2_epi,
3615
+ "tau": tau,
3616
+ "timestamp": len(G.nodes[node].get("glyph_history", [])),
3617
+ }
3618
+ )
3619
+
3620
+ # Log informative message
3621
+ logger.info(
3622
+ f"Node {node}: ZHIR bifurcation potential detected "
3623
+ f"(∂²EPI/∂t²={d2_epi:.3f} > τ={tau}). "
3624
+ f"Consider applying THOL for controlled bifurcation or IL for stabilization."
3625
+ )
3626
+
3627
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
3628
+ """Validate ZHIR-specific preconditions."""
3629
+ from .preconditions import validate_mutation
3630
+
3631
+ validate_mutation(G, node)
3632
+
3633
+ def _verify_postconditions(
3634
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
3635
+ ) -> None:
3636
+ """Verify ZHIR-specific postconditions.
3637
+
3638
+ Ensures that ZHIR fulfilled its contract:
3639
+ 1. Phase was transformed (θ changed)
3640
+ 2. Identity preserved (epi_kind maintained)
3641
+ 3. Bifurcation handled (if detected)
3642
+
3643
+ Parameters
3644
+ ----------
3645
+ G : TNFRGraph
3646
+ Graph containing the node
3647
+ node : Any
3648
+ Node that was mutated
3649
+ state_before : dict
3650
+ Node state before operator application, containing:
3651
+ - theta: Phase value before mutation
3652
+ - epi_kind: Identity before mutation (if tracked)
3653
+ """
3654
+ from .postconditions.mutation import (
3655
+ verify_phase_transformed,
3656
+ verify_identity_preserved,
3657
+ verify_bifurcation_handled,
3658
+ )
3659
+
3660
+ # Verify phase transformation
3661
+ verify_phase_transformed(G, node, state_before["theta"])
3662
+
3663
+ # Verify identity preservation (if tracked)
3664
+ epi_kind_before = state_before.get("epi_kind")
3665
+ if epi_kind_before is not None:
3666
+ verify_identity_preserved(G, node, epi_kind_before)
3667
+
3668
+ # Verify bifurcation handling
3669
+ verify_bifurcation_handled(G, node)
3670
+
3671
+ def _collect_metrics(
3672
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
3673
+ ) -> dict[str, Any]:
3674
+ """Collect ZHIR-specific metrics."""
3675
+ from .metrics import mutation_metrics
3676
+
3677
+ return mutation_metrics(
3678
+ G,
3679
+ node,
3680
+ state_before["theta"],
3681
+ state_before["epi"],
3682
+ vf_before=state_before.get("vf"),
3683
+ dnfr_before=state_before.get("dnfr"),
3684
+ )
3685
+
3686
+
3687
+ @register_operator
3688
+ class Transition(Operator):
3689
+ """Transition structural operator (NAV) - Controlled regime handoff.
3690
+
3691
+ Activates glyph ``NAV`` to guide the node through a controlled transition between
3692
+ structural regimes, managing hand-offs across states.
3693
+
3694
+ TNFR Context: Transition (NAV) manages movement between coherence regimes with minimal
3695
+ disruption. NAV adjusts θ, νf, and ΔNFR to navigate thresholds smoothly, preventing
3696
+ collapse during regime shifts. Essential for change management.
3697
+
3698
+ Use Cases: State transitions, regime changes, threshold crossings, transformation
3699
+ processes, managed evolution.
3700
+
3701
+ Typical Sequences: AL → NAV → IL (activate-transition-stabilize), NAV → ZHIR (transition
3702
+ enables mutation), SHA → NAV → AL (silence-transition-reactivation), IL → NAV → OZ
3703
+ (stable-transition-explore).
3704
+
3705
+ Versatility: NAV is highly compatible with most operators as transition manager.
3706
+
3707
+ Examples
3708
+ --------
3709
+ >>> from tnfr.constants import DNFR_PRIMARY, THETA_PRIMARY, VF_PRIMARY
3710
+ >>> from tnfr.dynamics import set_delta_nfr_hook
3711
+ >>> from tnfr.structural import create_nfr, run_sequence
3712
+ >>> from tnfr.operators.definitions import Transition
3713
+ >>> G, node = create_nfr("mu", vf=0.85, theta=0.40)
3714
+ >>> ramps = iter([(0.12, -0.25)])
3715
+ >>> def handoff(graph):
3716
+ ... d_vf, d_theta = next(ramps)
3717
+ ... graph.nodes[node][VF_PRIMARY] += d_vf
3718
+ ... graph.nodes[node][THETA_PRIMARY] += d_theta
3719
+ ... graph.nodes[node][DNFR_PRIMARY] = abs(d_vf) * 0.5
3720
+ >>> set_delta_nfr_hook(G, handoff)
3721
+ >>> run_sequence(G, node, [Transition()])
3722
+ >>> round(G.nodes[node][VF_PRIMARY], 2)
3723
+ 0.97
3724
+ >>> round(G.nodes[node][THETA_PRIMARY], 2)
3725
+ 0.15
3726
+ >>> round(G.nodes[node][DNFR_PRIMARY], 2)
3727
+ 0.06
3728
+
3729
+ **Biomedical**: Sleep stage transitions, developmental phases, recovery processes
3730
+ **Cognitive**: Learning phase transitions, attention shifts, mode switching
3731
+ **Social**: Organizational change, cultural transitions, leadership handoffs
3732
+ """
3733
+
3734
+ __slots__ = ()
3735
+ name: ClassVar[str] = TRANSITION
3736
+ glyph: ClassVar[Glyph] = Glyph.NAV
3737
+
3738
+ def __call__(self, G: TNFRGraph, node: Any, **kw: Any) -> None:
3739
+ """Apply NAV with regime detection and controlled transition.
3740
+
3741
+ Implements TNFR.pdf §2.3.11 canonical transition logic:
3742
+ 1. Detect current structural regime (latent/active/resonant)
3743
+ 2. Handle latency reactivation if node was in silence (SHA → NAV)
3744
+ 3. Apply grammar and structural transformation
3745
+ 4. Collect metrics (if enabled)
3746
+
3747
+ Parameters
3748
+ ----------
3749
+ G : TNFRGraph
3750
+ Graph storing TNFR nodes and structural operator history.
3751
+ node : Any
3752
+ Identifier or object representing the target node within ``G``.
3753
+ **kw : Any
3754
+ Additional keyword arguments:
3755
+ - phase_shift (float): Override default phase shift per regime
3756
+ - vf_factor (float): Override νf scaling for active regime (default: 1.0)
3757
+ - Other args forwarded to grammar layer
3758
+
3759
+ Notes
3760
+ -----
3761
+ Regime-specific transformations (TNFR.pdf §2.3.11):
3762
+
3763
+ **Latent → Active** (νf < 0.05 or latent flag):
3764
+ - νf × 1.2 (20% increase for gradual reactivation)
3765
+ - θ + 0.1 rad (small phase shift)
3766
+ - ΔNFR × 0.7 (30% reduction for smooth transition)
3767
+
3768
+ **Active** (baseline state):
3769
+ - νf × vf_factor (default 1.0, configurable)
3770
+ - θ + 0.2 rad (standard phase shift)
3771
+ - ΔNFR × 0.8 (20% reduction)
3772
+
3773
+ **Resonant → Active** (EPI > 0.5 AND νf > 0.8):
3774
+ - νf × 0.95 (5% reduction for stability)
3775
+ - θ + 0.15 rad (careful phase shift)
3776
+ - ΔNFR × 0.9 (10% reduction, gentle)
3777
+
3778
+ Telemetry stored in G.graph["_nav_transitions"] tracks:
3779
+ - regime_origin, vf_before/after, theta_before/after, dnfr_before/after
3780
+ """
3781
+ from ..alias import get_attr, set_attr
3782
+ from ..constants.aliases import ALIAS_DNFR, ALIAS_EPI, ALIAS_THETA, ALIAS_VF
3783
+
3784
+ # 1. Detect current regime and store for metrics collection
3785
+ current_regime = self._detect_regime(G, node)
3786
+ G.nodes[node]["_regime_before"] = current_regime
3787
+
3788
+ # 2. Handle latency reactivation if applicable
3789
+ if G.nodes[node].get("latent", False):
3790
+ self._handle_latency_transition(G, node)
3791
+
3792
+ # 3. Validate preconditions (if enabled)
3793
+ validate_preconditions = kw.get("validate_preconditions", True) or G.graph.get(
3794
+ "VALIDATE_PRECONDITIONS", False
3795
+ )
3796
+ if validate_preconditions:
3797
+ self._validate_preconditions(G, node)
3798
+
3799
+ # 4. Capture state before for metrics/validation
3800
+ collect_metrics = kw.get("collect_metrics", False) or G.graph.get(
3801
+ "COLLECT_OPERATOR_METRICS", False
3802
+ )
3803
+ validate_equation = kw.get("validate_nodal_equation", False) or G.graph.get(
3804
+ "VALIDATE_NODAL_EQUATION", False
3805
+ )
3806
+
3807
+ state_before = None
3808
+ if collect_metrics or validate_equation:
3809
+ state_before = self._capture_state(G, node)
3810
+
3811
+ # 5. Apply grammar
3812
+ from . import apply_glyph_with_grammar
3813
+ apply_glyph_with_grammar(G, [node], self.glyph, kw.get("window"))
3814
+
3815
+ # 6. Execute structural transition (BEFORE metrics collection)
3816
+ self._apply_structural_transition(G, node, current_regime, **kw)
3817
+
3818
+ # 7. Optional nodal equation validation
3819
+ if validate_equation and state_before is not None:
3820
+ from ..alias import get_attr
3821
+ from ..constants.aliases import ALIAS_EPI
3822
+ from .nodal_equation import validate_nodal_equation
3823
+
3824
+ dt = float(kw.get("dt", 1.0))
3825
+ strict = G.graph.get("NODAL_EQUATION_STRICT", False)
3826
+ epi_after = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
3827
+
3828
+ validate_nodal_equation(
3829
+ G,
3830
+ node,
3831
+ epi_before=state_before["epi"],
3832
+ epi_after=epi_after,
3833
+ dt=dt,
3834
+ operator_name=self.name,
3835
+ strict=strict,
3836
+ )
3837
+
3838
+ # 8. Optional metrics collection (AFTER structural transformation)
3839
+ if collect_metrics and state_before is not None:
3840
+ metrics = self._collect_metrics(G, node, state_before)
3841
+ if "operator_metrics" not in G.graph:
3842
+ G.graph["operator_metrics"] = []
3843
+ G.graph["operator_metrics"].append(metrics)
3844
+
3845
+ def _detect_regime(self, G: TNFRGraph, node: Any) -> str:
3846
+ """Detect current structural regime: latent/active/resonant.
3847
+
3848
+ Parameters
3849
+ ----------
3850
+ G : TNFRGraph
3851
+ Graph containing the node.
3852
+ node : Any
3853
+ Target node.
3854
+
3855
+ Returns
3856
+ -------
3857
+ str
3858
+ Regime classification: "latent", "active", or "resonant"
3859
+
3860
+ Notes
3861
+ -----
3862
+ Classification criteria:
3863
+ - **Latent**: latent flag set OR νf < 0.05 (minimal reorganization capacity)
3864
+ - **Resonant**: EPI > 0.5 AND νf > 0.8 (high form + high frequency)
3865
+ - **Active**: Default (baseline operational state)
3866
+ """
3867
+ from ..alias import get_attr
3868
+ from ..constants.aliases import ALIAS_EPI, ALIAS_VF
3869
+
3870
+ epi = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
3871
+ vf = float(get_attr(G.nodes[node], ALIAS_VF, 0.0))
3872
+ latent = G.nodes[node].get("latent", False)
3873
+
3874
+ if latent or vf < 0.05:
3875
+ return "latent"
3876
+ elif epi > 0.5 and vf > 0.8:
3877
+ return "resonant"
3878
+ else:
3879
+ return "active"
3880
+
3881
+ def _handle_latency_transition(self, G: TNFRGraph, node: Any) -> None:
3882
+ """Handle transition from latent state (SHA → NAV flow).
3883
+
3884
+ Similar to Emission._check_reactivation but for NAV-specific transitions.
3885
+ Validates silence duration and clears latency attributes.
3886
+
3887
+ Parameters
3888
+ ----------
3889
+ G : TNFRGraph
3890
+ Graph containing the node.
3891
+ node : Any
3892
+ Target node being reactivated.
3893
+
3894
+ Warnings
3895
+ --------
3896
+ - Warns if node transitioning after extended silence (duration > MAX_SILENCE_DURATION)
3897
+ - Warns if EPI drifted significantly during silence (> 1% tolerance)
3898
+
3899
+ Notes
3900
+ -----
3901
+ Clears latency-related attributes:
3902
+ - latent (flag)
3903
+ - latency_start_time (ISO timestamp)
3904
+ - preserved_epi (EPI snapshot from SHA)
3905
+ - silence_duration (computed duration)
3906
+ """
3907
+ from datetime import datetime, timezone
3908
+
3909
+ # Verify silence duration if timestamp available
3910
+ if "latency_start_time" in G.nodes[node]:
3911
+ start = datetime.fromisoformat(G.nodes[node]["latency_start_time"])
3912
+ duration = (datetime.now(timezone.utc) - start).total_seconds()
3913
+ G.nodes[node]["silence_duration"] = duration
3914
+
3915
+ max_silence = G.graph.get("MAX_SILENCE_DURATION", float("inf"))
3916
+ if duration > max_silence:
3917
+ warnings.warn(
3918
+ f"Node {node} transitioning after extended silence "
3919
+ f"(duration: {duration:.2f}s, max: {max_silence:.2f}s)",
3920
+ stacklevel=4,
3921
+ )
3922
+
3923
+ # Check EPI preservation integrity
3924
+ preserved_epi = G.nodes[node].get("preserved_epi")
3925
+ if preserved_epi is not None:
3926
+ from ..alias import get_attr
3927
+ from ..constants.aliases import ALIAS_EPI
3928
+
3929
+ current_epi = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
3930
+ epi_drift = abs(current_epi - preserved_epi)
3931
+
3932
+ # Allow small numerical drift (1% tolerance)
3933
+ if epi_drift > 0.01 * abs(preserved_epi):
3934
+ warnings.warn(
3935
+ f"Node {node} EPI drifted during silence "
3936
+ f"(preserved: {preserved_epi:.3f}, current: {current_epi:.3f}, "
3937
+ f"drift: {epi_drift:.3f})",
3938
+ stacklevel=4,
3939
+ )
3940
+
3941
+ # Clear latency state
3942
+ del G.nodes[node]["latent"]
3943
+ if "latency_start_time" in G.nodes[node]:
3944
+ del G.nodes[node]["latency_start_time"]
3945
+ if "preserved_epi" in G.nodes[node]:
3946
+ del G.nodes[node]["preserved_epi"]
3947
+ # Keep silence_duration for telemetry/metrics - don't delete it
3948
+
3949
+ def _apply_structural_transition(
3950
+ self, G: TNFRGraph, node: Any, regime: str, **kw: Any
3951
+ ) -> None:
3952
+ """Apply structural transformation based on regime origin.
3953
+
3954
+ Parameters
3955
+ ----------
3956
+ G : TNFRGraph
3957
+ Graph containing the node.
3958
+ node : Any
3959
+ Target node.
3960
+ regime : str
3961
+ Origin regime: "latent", "active", or "resonant"
3962
+ **kw : Any
3963
+ Optional overrides:
3964
+ - phase_shift (float): Custom phase shift
3965
+ - vf_factor (float): Custom νf scaling for active regime
3966
+
3967
+ Notes
3968
+ -----
3969
+ Applies regime-specific transformations to θ, νf, and ΔNFR following
3970
+ TNFR.pdf §2.3.11. All changes use canonical alias system (set_attr)
3971
+ to ensure proper attribute resolution.
3972
+
3973
+ Telemetry appended to G.graph["_nav_transitions"] for analysis.
3974
+ """
3975
+ from ..alias import get_attr, set_attr
3976
+ from ..constants.aliases import ALIAS_DNFR, ALIAS_THETA, ALIAS_VF
3977
+
3978
+ # Get current state
3979
+ theta = float(get_attr(G.nodes[node], ALIAS_THETA, 0.0))
3980
+ vf = float(get_attr(G.nodes[node], ALIAS_VF, 1.0))
3981
+ dnfr = float(get_attr(G.nodes[node], ALIAS_DNFR, 0.0))
3982
+
3983
+ # Apply regime-specific adjustments
3984
+ if regime == "latent":
3985
+ # Latent → Active: gradual reactivation
3986
+ vf_new = vf * 1.2 # 20% increase
3987
+ theta_shift = kw.get("phase_shift", 0.1) # Small phase shift
3988
+ theta_new = (theta + theta_shift) % (2 * math.pi)
3989
+ dnfr_new = dnfr * 0.7 # 30% reduction for smooth transition
3990
+ elif regime == "active":
3991
+ # Active: standard transition
3992
+ vf_new = vf * kw.get("vf_factor", 1.0) # Configurable
3993
+ theta_shift = kw.get("phase_shift", 0.2) # Standard shift
3994
+ theta_new = (theta + theta_shift) % (2 * math.pi)
3995
+ dnfr_new = dnfr * 0.8 # 20% reduction
3996
+ else: # resonant
3997
+ # Resonant → Active: careful transition (high energy state)
3998
+ vf_new = vf * 0.95 # 5% reduction for stability
3999
+ theta_shift = kw.get("phase_shift", 0.15) # Careful phase shift
4000
+ theta_new = (theta + theta_shift) % (2 * math.pi)
4001
+ dnfr_new = dnfr * 0.9 # 10% reduction, gentle
4002
+
4003
+ # Apply changes via canonical alias system
4004
+ set_attr(G.nodes[node], ALIAS_VF, vf_new)
4005
+ set_attr(G.nodes[node], ALIAS_THETA, theta_new)
4006
+ set_attr(G.nodes[node], ALIAS_DNFR, dnfr_new)
4007
+
4008
+ # Telemetry tracking
4009
+ if "_nav_transitions" not in G.graph:
4010
+ G.graph["_nav_transitions"] = []
4011
+ G.graph["_nav_transitions"].append(
4012
+ {
4013
+ "node": node,
4014
+ "regime_origin": regime,
4015
+ "vf_before": vf,
4016
+ "vf_after": vf_new,
4017
+ "theta_before": theta,
4018
+ "theta_after": theta_new,
4019
+ "dnfr_before": dnfr,
4020
+ "dnfr_after": dnfr_new,
4021
+ "phase_shift": theta_new - theta,
4022
+ }
4023
+ )
4024
+
4025
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
4026
+ """Validate NAV-specific preconditions."""
4027
+ from .preconditions import validate_transition
4028
+
4029
+ validate_transition(G, node)
4030
+
4031
+ def _collect_metrics(
4032
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
4033
+ ) -> dict[str, Any]:
4034
+ """Collect NAV-specific metrics."""
4035
+ from .metrics import transition_metrics
4036
+
4037
+ return transition_metrics(
4038
+ G,
4039
+ node,
4040
+ state_before["dnfr"],
4041
+ state_before["vf"],
4042
+ state_before["theta"],
4043
+ epi_before=state_before.get("epi"),
4044
+ )
4045
+
4046
+
4047
+ @register_operator
4048
+ class Recursivity(Operator):
4049
+ """Recursivity structural operator (REMESH) - Fractal pattern propagation.
4050
+
4051
+ Activates glyph ``REMESH`` to propagate fractal recursivity and echo structural
4052
+ patterns across nested EPIs, maintaining multi-scale identity.
4053
+
4054
+ TNFR Context: Recursivity (REMESH) implements operational fractality - patterns that
4055
+ replicate across scales while preserving structural identity. REMESH ensures that
4056
+ EPI(t) echoes EPI(t - τ) at nested levels, creating self-similar coherence structures.
4057
+
4058
+ Use Cases: Fractal processes, multi-scale coherence, memory recursion, pattern
4059
+ replication, self-similar organization, adaptive memory systems.
4060
+
4061
+ Typical Sequences: REMESH → RA (recursive propagation), THOL → REMESH (emergence
4062
+ with fractal structure), REMESH → IL (recursive pattern stabilization), VAL → REMESH
4063
+ (expansion with self-similarity).
4064
+
4065
+ Critical: REMESH preserves identity across scales - fundamental to TNFR fractality.
4066
+
4067
+ Examples
4068
+ --------
4069
+ >>> from tnfr.constants import EPI_PRIMARY, VF_PRIMARY
4070
+ >>> from tnfr.dynamics import set_delta_nfr_hook
4071
+ >>> from tnfr.structural import create_nfr, run_sequence
4072
+ >>> from tnfr.operators.definitions import Recursivity
4073
+ >>> G, node = create_nfr("nu", epi=0.52, vf=0.92)
4074
+ >>> echoes = iter([(0.02, 0.03)])
4075
+ >>> def echo(graph):
4076
+ ... d_epi, d_vf = next(echoes)
4077
+ ... graph.nodes[node][EPI_PRIMARY] += d_epi
4078
+ ... graph.nodes[node][VF_PRIMARY] += d_vf
4079
+ ... graph.graph.setdefault("echo_trace", []).append(
4080
+ ... (round(graph.nodes[node][EPI_PRIMARY], 2), round(graph.nodes[node][VF_PRIMARY], 2))
4081
+ ... )
4082
+ >>> set_delta_nfr_hook(G, echo)
4083
+ >>> run_sequence(G, node, [Recursivity()])
4084
+ >>> G.graph["echo_trace"]
4085
+ [(0.54, 0.95)]
4086
+
4087
+ **Biomedical**: Fractal physiology (HRV, EEG), developmental recapitulation
4088
+ **Cognitive**: Recursive thinking, meta-cognition, self-referential processes
4089
+ **Social**: Cultural fractals, organizational self-similarity, meme propagation
4090
+ """
4091
+
4092
+ __slots__ = ()
4093
+ name: ClassVar[str] = RECURSIVITY
4094
+ glyph: ClassVar[Glyph] = Glyph.REMESH
4095
+
4096
+ def _validate_preconditions(self, G: TNFRGraph, node: Any) -> None:
4097
+ """Validate REMESH-specific preconditions."""
4098
+ from .preconditions import validate_recursivity
4099
+
4100
+ validate_recursivity(G, node)
4101
+
4102
+ def _collect_metrics(
4103
+ self, G: TNFRGraph, node: Any, state_before: dict[str, Any]
4104
+ ) -> dict[str, Any]:
4105
+ """Collect REMESH-specific metrics."""
4106
+ from .metrics import recursivity_metrics
4107
+
4108
+ return recursivity_metrics(G, node, state_before["epi"], state_before["vf"])