tnfr 3.0.3__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 (360) hide show
  1. tnfr/__init__.py +375 -56
  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 +723 -0
  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 +171 -0
  15. tnfr/cache.pyi +13 -0
  16. tnfr/cli/__init__.py +110 -0
  17. tnfr/cli/__init__.pyi +26 -0
  18. tnfr/cli/arguments.py +489 -0
  19. tnfr/cli/arguments.pyi +29 -0
  20. tnfr/cli/execution.py +914 -0
  21. tnfr/cli/execution.pyi +70 -0
  22. tnfr/cli/interactive_validator.py +614 -0
  23. tnfr/cli/utils.py +51 -0
  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/config/constants.py +104 -0
  34. tnfr/config/constants.pyi +12 -0
  35. tnfr/config/defaults.py +54 -0
  36. tnfr/config/defaults_core.py +212 -0
  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 +92 -0
  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 +33 -0
  57. tnfr/constants/init.pyi +12 -0
  58. tnfr/constants/metric.py +104 -0
  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 +238 -0
  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 +3034 -0
  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 +661 -0
  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 +36 -0
  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 +223 -0
  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 +262 -0
  125. tnfr/flatten.pyi +21 -0
  126. tnfr/gamma.py +354 -0
  127. tnfr/gamma.pyi +36 -0
  128. tnfr/glyph_history.py +377 -0
  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 +218 -0
  133. tnfr/immutable.pyi +36 -0
  134. tnfr/initialization.py +203 -0
  135. tnfr/initialization.pyi +65 -0
  136. tnfr/io.py +10 -0
  137. tnfr/io.pyi +13 -0
  138. tnfr/locking.py +37 -0
  139. tnfr/locking.pyi +7 -0
  140. tnfr/mathematics/__init__.py +79 -0
  141. tnfr/mathematics/backend.py +453 -0
  142. tnfr/mathematics/backend.pyi +99 -0
  143. tnfr/mathematics/dynamics.py +408 -0
  144. tnfr/mathematics/dynamics.pyi +90 -0
  145. tnfr/mathematics/epi.py +391 -0
  146. tnfr/mathematics/epi.pyi +65 -0
  147. tnfr/mathematics/generators.py +242 -0
  148. tnfr/mathematics/generators.pyi +29 -0
  149. tnfr/mathematics/metrics.py +119 -0
  150. tnfr/mathematics/metrics.pyi +16 -0
  151. tnfr/mathematics/operators.py +239 -0
  152. tnfr/mathematics/operators.pyi +59 -0
  153. tnfr/mathematics/operators_factory.py +124 -0
  154. tnfr/mathematics/operators_factory.pyi +11 -0
  155. tnfr/mathematics/projection.py +87 -0
  156. tnfr/mathematics/projection.pyi +33 -0
  157. tnfr/mathematics/runtime.py +182 -0
  158. tnfr/mathematics/runtime.pyi +64 -0
  159. tnfr/mathematics/spaces.py +256 -0
  160. tnfr/mathematics/spaces.pyi +83 -0
  161. tnfr/mathematics/transforms.py +305 -0
  162. tnfr/mathematics/transforms.pyi +62 -0
  163. tnfr/metrics/__init__.py +79 -0
  164. tnfr/metrics/__init__.pyi +20 -0
  165. tnfr/metrics/buffer_cache.py +163 -0
  166. tnfr/metrics/buffer_cache.pyi +24 -0
  167. tnfr/metrics/cache_utils.py +214 -0
  168. tnfr/metrics/coherence.py +2009 -0
  169. tnfr/metrics/coherence.pyi +129 -0
  170. tnfr/metrics/common.py +158 -0
  171. tnfr/metrics/common.pyi +35 -0
  172. tnfr/metrics/core.py +316 -0
  173. tnfr/metrics/core.pyi +13 -0
  174. tnfr/metrics/diagnosis.py +833 -0
  175. tnfr/metrics/diagnosis.pyi +86 -0
  176. tnfr/metrics/emergence.py +245 -0
  177. tnfr/metrics/export.py +179 -0
  178. tnfr/metrics/export.pyi +7 -0
  179. tnfr/metrics/glyph_timing.py +379 -0
  180. tnfr/metrics/glyph_timing.pyi +81 -0
  181. tnfr/metrics/learning_metrics.py +280 -0
  182. tnfr/metrics/learning_metrics.pyi +21 -0
  183. tnfr/metrics/phase_coherence.py +351 -0
  184. tnfr/metrics/phase_compatibility.py +349 -0
  185. tnfr/metrics/reporting.py +183 -0
  186. tnfr/metrics/reporting.pyi +25 -0
  187. tnfr/metrics/sense_index.py +1203 -0
  188. tnfr/metrics/sense_index.pyi +9 -0
  189. tnfr/metrics/trig.py +373 -0
  190. tnfr/metrics/trig.pyi +13 -0
  191. tnfr/metrics/trig_cache.py +233 -0
  192. tnfr/metrics/trig_cache.pyi +10 -0
  193. tnfr/multiscale/__init__.py +32 -0
  194. tnfr/multiscale/hierarchical.py +517 -0
  195. tnfr/node.py +763 -0
  196. tnfr/node.pyi +139 -0
  197. tnfr/observers.py +255 -130
  198. tnfr/observers.pyi +31 -0
  199. tnfr/ontosim.py +144 -137
  200. tnfr/ontosim.pyi +28 -0
  201. tnfr/operators/__init__.py +1672 -0
  202. tnfr/operators/__init__.pyi +31 -0
  203. tnfr/operators/algebra.py +277 -0
  204. tnfr/operators/canonical_patterns.py +420 -0
  205. tnfr/operators/cascade.py +267 -0
  206. tnfr/operators/cycle_detection.py +358 -0
  207. tnfr/operators/definitions.py +4108 -0
  208. tnfr/operators/definitions.pyi +78 -0
  209. tnfr/operators/grammar.py +1164 -0
  210. tnfr/operators/grammar.pyi +140 -0
  211. tnfr/operators/hamiltonian.py +710 -0
  212. tnfr/operators/health_analyzer.py +809 -0
  213. tnfr/operators/jitter.py +272 -0
  214. tnfr/operators/jitter.pyi +11 -0
  215. tnfr/operators/lifecycle.py +314 -0
  216. tnfr/operators/metabolism.py +618 -0
  217. tnfr/operators/metrics.py +2138 -0
  218. tnfr/operators/network_analysis/__init__.py +27 -0
  219. tnfr/operators/network_analysis/source_detection.py +186 -0
  220. tnfr/operators/nodal_equation.py +395 -0
  221. tnfr/operators/pattern_detection.py +660 -0
  222. tnfr/operators/patterns.py +669 -0
  223. tnfr/operators/postconditions/__init__.py +38 -0
  224. tnfr/operators/postconditions/mutation.py +236 -0
  225. tnfr/operators/preconditions/__init__.py +1226 -0
  226. tnfr/operators/preconditions/coherence.py +305 -0
  227. tnfr/operators/preconditions/dissonance.py +236 -0
  228. tnfr/operators/preconditions/emission.py +128 -0
  229. tnfr/operators/preconditions/mutation.py +580 -0
  230. tnfr/operators/preconditions/reception.py +125 -0
  231. tnfr/operators/preconditions/resonance.py +364 -0
  232. tnfr/operators/registry.py +74 -0
  233. tnfr/operators/registry.pyi +9 -0
  234. tnfr/operators/remesh.py +1809 -0
  235. tnfr/operators/remesh.pyi +26 -0
  236. tnfr/operators/structural_units.py +268 -0
  237. tnfr/operators/unified_grammar.py +105 -0
  238. tnfr/parallel/__init__.py +54 -0
  239. tnfr/parallel/auto_scaler.py +234 -0
  240. tnfr/parallel/distributed.py +384 -0
  241. tnfr/parallel/engine.py +238 -0
  242. tnfr/parallel/gpu_engine.py +420 -0
  243. tnfr/parallel/monitoring.py +248 -0
  244. tnfr/parallel/partitioner.py +459 -0
  245. tnfr/py.typed +0 -0
  246. tnfr/recipes/__init__.py +22 -0
  247. tnfr/recipes/cookbook.py +743 -0
  248. tnfr/rng.py +178 -0
  249. tnfr/rng.pyi +26 -0
  250. tnfr/schemas/__init__.py +8 -0
  251. tnfr/schemas/grammar.json +94 -0
  252. tnfr/sdk/__init__.py +107 -0
  253. tnfr/sdk/__init__.pyi +19 -0
  254. tnfr/sdk/adaptive_system.py +173 -0
  255. tnfr/sdk/adaptive_system.pyi +21 -0
  256. tnfr/sdk/builders.py +370 -0
  257. tnfr/sdk/builders.pyi +51 -0
  258. tnfr/sdk/fluent.py +1121 -0
  259. tnfr/sdk/fluent.pyi +74 -0
  260. tnfr/sdk/templates.py +342 -0
  261. tnfr/sdk/templates.pyi +41 -0
  262. tnfr/sdk/utils.py +341 -0
  263. tnfr/secure_config.py +46 -0
  264. tnfr/security/__init__.py +70 -0
  265. tnfr/security/database.py +514 -0
  266. tnfr/security/subprocess.py +503 -0
  267. tnfr/security/validation.py +290 -0
  268. tnfr/selector.py +247 -0
  269. tnfr/selector.pyi +19 -0
  270. tnfr/sense.py +378 -0
  271. tnfr/sense.pyi +23 -0
  272. tnfr/services/__init__.py +17 -0
  273. tnfr/services/orchestrator.py +325 -0
  274. tnfr/sparse/__init__.py +39 -0
  275. tnfr/sparse/representations.py +492 -0
  276. tnfr/structural.py +705 -0
  277. tnfr/structural.pyi +83 -0
  278. tnfr/telemetry/__init__.py +35 -0
  279. tnfr/telemetry/cache_metrics.py +226 -0
  280. tnfr/telemetry/cache_metrics.pyi +64 -0
  281. tnfr/telemetry/nu_f.py +422 -0
  282. tnfr/telemetry/nu_f.pyi +108 -0
  283. tnfr/telemetry/verbosity.py +36 -0
  284. tnfr/telemetry/verbosity.pyi +15 -0
  285. tnfr/tokens.py +58 -0
  286. tnfr/tokens.pyi +36 -0
  287. tnfr/tools/__init__.py +20 -0
  288. tnfr/tools/domain_templates.py +478 -0
  289. tnfr/tools/sequence_generator.py +846 -0
  290. tnfr/topology/__init__.py +13 -0
  291. tnfr/topology/asymmetry.py +151 -0
  292. tnfr/trace.py +543 -0
  293. tnfr/trace.pyi +42 -0
  294. tnfr/tutorials/__init__.py +38 -0
  295. tnfr/tutorials/autonomous_evolution.py +285 -0
  296. tnfr/tutorials/interactive.py +1576 -0
  297. tnfr/tutorials/structural_metabolism.py +238 -0
  298. tnfr/types.py +775 -0
  299. tnfr/types.pyi +357 -0
  300. tnfr/units.py +68 -0
  301. tnfr/units.pyi +13 -0
  302. tnfr/utils/__init__.py +282 -0
  303. tnfr/utils/__init__.pyi +215 -0
  304. tnfr/utils/cache.py +4223 -0
  305. tnfr/utils/cache.pyi +470 -0
  306. tnfr/utils/callbacks.py +375 -0
  307. tnfr/utils/callbacks.pyi +49 -0
  308. tnfr/utils/chunks.py +108 -0
  309. tnfr/utils/chunks.pyi +22 -0
  310. tnfr/utils/data.py +428 -0
  311. tnfr/utils/data.pyi +74 -0
  312. tnfr/utils/graph.py +85 -0
  313. tnfr/utils/graph.pyi +10 -0
  314. tnfr/utils/init.py +821 -0
  315. tnfr/utils/init.pyi +80 -0
  316. tnfr/utils/io.py +559 -0
  317. tnfr/utils/io.pyi +66 -0
  318. tnfr/utils/numeric.py +114 -0
  319. tnfr/utils/numeric.pyi +21 -0
  320. tnfr/validation/__init__.py +257 -0
  321. tnfr/validation/__init__.pyi +85 -0
  322. tnfr/validation/compatibility.py +460 -0
  323. tnfr/validation/compatibility.pyi +6 -0
  324. tnfr/validation/config.py +73 -0
  325. tnfr/validation/graph.py +139 -0
  326. tnfr/validation/graph.pyi +18 -0
  327. tnfr/validation/input_validation.py +755 -0
  328. tnfr/validation/invariants.py +712 -0
  329. tnfr/validation/rules.py +253 -0
  330. tnfr/validation/rules.pyi +44 -0
  331. tnfr/validation/runtime.py +279 -0
  332. tnfr/validation/runtime.pyi +28 -0
  333. tnfr/validation/sequence_validator.py +162 -0
  334. tnfr/validation/soft_filters.py +170 -0
  335. tnfr/validation/soft_filters.pyi +32 -0
  336. tnfr/validation/spectral.py +164 -0
  337. tnfr/validation/spectral.pyi +42 -0
  338. tnfr/validation/validator.py +1266 -0
  339. tnfr/validation/window.py +39 -0
  340. tnfr/validation/window.pyi +1 -0
  341. tnfr/visualization/__init__.py +98 -0
  342. tnfr/visualization/cascade_viz.py +256 -0
  343. tnfr/visualization/hierarchy.py +284 -0
  344. tnfr/visualization/sequence_plotter.py +784 -0
  345. tnfr/viz/__init__.py +60 -0
  346. tnfr/viz/matplotlib.py +278 -0
  347. tnfr/viz/matplotlib.pyi +35 -0
  348. tnfr-8.5.0.dist-info/METADATA +573 -0
  349. tnfr-8.5.0.dist-info/RECORD +353 -0
  350. tnfr-8.5.0.dist-info/entry_points.txt +3 -0
  351. tnfr-3.0.3.dist-info/licenses/LICENSE.txt → tnfr-8.5.0.dist-info/licenses/LICENSE.md +1 -1
  352. tnfr/constants.py +0 -183
  353. tnfr/dynamics.py +0 -543
  354. tnfr/helpers.py +0 -198
  355. tnfr/main.py +0 -37
  356. tnfr/operators.py +0 -296
  357. tnfr-3.0.3.dist-info/METADATA +0 -35
  358. tnfr-3.0.3.dist-info/RECORD +0 -13
  359. {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
  360. {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,189 @@
1
+ """Adaptive sequence selection for TNFR operator trajectories.
2
+
3
+ This module implements learning-based selection of operator sequences.
4
+ Rather than executing fixed sequences, the system learns which sequences
5
+ work best for given contexts and adapts its selection over time.
6
+
7
+ The approach combines predefined canonical sequences with epsilon-greedy
8
+ exploration to balance exploitation (use known good sequences) with
9
+ exploration (try new patterns).
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import random
15
+ from typing import TYPE_CHECKING, Any, Dict, List
16
+
17
+ if TYPE_CHECKING:
18
+ from ..types import TNFRGraph, NodeId
19
+
20
+ try:
21
+ import numpy as np
22
+ except ImportError:
23
+ np = None # type: ignore[assignment]
24
+
25
+ from ..config.operator_names import (
26
+ COHERENCE,
27
+ DISSONANCE,
28
+ EMISSION,
29
+ MUTATION,
30
+ RECEPTION,
31
+ RECURSIVITY,
32
+ RESONANCE,
33
+ SELF_ORGANIZATION,
34
+ SILENCE,
35
+ TRANSITION,
36
+ )
37
+
38
+ __all__ = ["AdaptiveSequenceSelector"]
39
+
40
+
41
+ class AdaptiveSequenceSelector:
42
+ """Learns and selects optimal operator sequences based on context.
43
+
44
+ This class maintains a pool of canonical operator sequences and tracks
45
+ their performance over time. It uses epsilon-greedy selection to balance
46
+ exploitation of known-good sequences with exploration of alternatives.
47
+
48
+ **Selection Strategy:**
49
+
50
+ - **Exploitation (80%)**: Choose sequence with best historical performance
51
+ - **Exploration (20%)**: Random selection to discover new patterns
52
+
53
+ Parameters
54
+ ----------
55
+ graph : TNFRGraph
56
+ Graph containing the node
57
+ node : NodeId
58
+ Identifier of the node
59
+
60
+ Attributes
61
+ ----------
62
+ G : TNFRGraph
63
+ Graph reference
64
+ node : NodeId
65
+ Node identifier
66
+ sequences : dict[str, list[str]]
67
+ Pool of canonical operator sequences
68
+ performance : dict[str, list[float]]
69
+ Historical performance for each sequence
70
+
71
+ Examples
72
+ --------
73
+ >>> from tnfr.structural import create_nfr
74
+ >>> from tnfr.dynamics.adaptive_sequences import AdaptiveSequenceSelector
75
+ >>> G, node = create_nfr("test_node")
76
+ >>> selector = AdaptiveSequenceSelector(G, node)
77
+ >>> context = {"goal": "stability", "urgency": 0.5}
78
+ >>> sequence = selector.select_sequence(context)
79
+ >>> selector.record_performance("basic_activation", 0.85)
80
+ """
81
+
82
+ def __init__(self, graph: TNFRGraph, node: NodeId) -> None:
83
+ self.G = graph
84
+ self.node = node
85
+
86
+ # Canonical operator sequences
87
+ # Note: Sequences are designed to comply with TNFR grammar rules
88
+ self.sequences: Dict[str, List[str]] = {
89
+ "basic_activation": [EMISSION, COHERENCE],
90
+ "deep_learning": [EMISSION, RECEPTION, COHERENCE],
91
+ "exploration": [EMISSION, DISSONANCE, COHERENCE],
92
+ "consolidation": [COHERENCE, SILENCE, RECURSIVITY],
93
+ "mutation": [COHERENCE, MUTATION, TRANSITION, COHERENCE],
94
+ }
95
+
96
+ # Performance history: sequence_name -> [coherence_gains]
97
+ self.performance: Dict[str, List[float]] = {
98
+ k: [] for k in self.sequences.keys()
99
+ }
100
+
101
+ def select_sequence(self, context: Dict[str, Any]) -> List[str]:
102
+ """Select optimal sequence based on context and historical performance.
103
+
104
+ Uses goal-based filtering and epsilon-greedy selection:
105
+
106
+ 1. Filter sequences appropriate for goal
107
+ 2. With probability 0.8: select best-performing sequence
108
+ 3. With probability 0.2: select random sequence (exploration)
109
+
110
+ Parameters
111
+ ----------
112
+ context : dict
113
+ Context with keys:
114
+
115
+ - **goal** (str): "stability", "growth", or "adaptation"
116
+ - **urgency** (float): Urgency level (0-1), currently unused
117
+
118
+ Returns
119
+ -------
120
+ list[str]
121
+ Sequence of operator names to execute
122
+
123
+ Notes
124
+ -----
125
+ Goal-to-sequence mapping follows TNFR principles:
126
+
127
+ - **stability**: Sequences emphasizing IL (Coherence) and SHA (Silence)
128
+ - **growth**: Sequences with AL (Emission) and THOL (Self-organization)
129
+ - **adaptation**: Sequences with ZHIR (Mutation) and learning cycles
130
+ """
131
+ goal = context.get("goal", "stability")
132
+
133
+ # Map goals to appropriate sequence candidates
134
+ if goal == "stability":
135
+ candidates = ["basic_activation", "consolidation"]
136
+ elif goal == "growth":
137
+ candidates = ["deep_learning", "exploration"]
138
+ elif goal == "adaptation":
139
+ candidates = ["mutation", "deep_learning"]
140
+ else:
141
+ candidates = list(self.sequences.keys())
142
+
143
+ # Epsilon-greedy selection (20% exploration, 80% exploitation)
144
+ epsilon = 0.2
145
+
146
+ if np is not None:
147
+ random_val = np.random.random()
148
+ else:
149
+ random_val = random.random()
150
+
151
+ if random_val < epsilon:
152
+ # Exploration: random selection
153
+ if np is not None:
154
+ selected = str(np.random.choice(candidates))
155
+ else:
156
+ selected = random.choice(candidates)
157
+ else:
158
+ # Exploitation: select best-performing sequence
159
+ avg_perf = {
160
+ k: (
161
+ sum(self.performance[k]) / len(self.performance[k])
162
+ if self.performance[k]
163
+ else 0.0
164
+ )
165
+ for k in candidates
166
+ }
167
+ selected = max(avg_perf, key=avg_perf.get) # type: ignore[arg-type]
168
+
169
+ return self.sequences[selected]
170
+
171
+ def record_performance(self, sequence_name: str, coherence_gain: float) -> None:
172
+ """Record performance metric for a sequence to enable learning.
173
+
174
+ Parameters
175
+ ----------
176
+ sequence_name : str
177
+ Name of the sequence that was executed
178
+ coherence_gain : float
179
+ Achieved coherence improvement or other performance metric
180
+
181
+ Notes
182
+ -----
183
+ Maintains a sliding window of the last 20 executions to adapt to
184
+ changing dynamics. Older performance data is discarded.
185
+ """
186
+ if sequence_name in self.performance:
187
+ self.performance[sequence_name].append(float(coherence_gain))
188
+ # Keep only last 20 executions (sliding window)
189
+ self.performance[sequence_name] = self.performance[sequence_name][-20:]
@@ -0,0 +1,14 @@
1
+ """Type stubs for tnfr.dynamics.adaptive_sequences module."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..types import TNFRGraph, NodeId
5
+
6
+ class AdaptiveSequenceSelector:
7
+ G: TNFRGraph
8
+ node: NodeId
9
+ sequences: Dict[str, List[str]]
10
+ performance: Dict[str, List[float]]
11
+
12
+ def __init__(self, graph: TNFRGraph, node: NodeId) -> None: ...
13
+ def select_sequence(self, context: Dict[str, Any]) -> List[str]: ...
14
+ def record_performance(self, sequence_name: str, coherence_gain: float) -> None: ...
@@ -0,0 +1,23 @@
1
+ """Shared alias tokens used across TNFR dynamics submodules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from ..constants.aliases import (
6
+ ALIAS_D2EPI,
7
+ ALIAS_DNFR,
8
+ ALIAS_DSI,
9
+ ALIAS_EPI,
10
+ ALIAS_SI,
11
+ ALIAS_THETA,
12
+ ALIAS_VF,
13
+ )
14
+
15
+ __all__ = (
16
+ "ALIAS_VF",
17
+ "ALIAS_DNFR",
18
+ "ALIAS_EPI",
19
+ "ALIAS_SI",
20
+ "ALIAS_THETA",
21
+ "ALIAS_D2EPI",
22
+ "ALIAS_DSI",
23
+ )
@@ -0,0 +1,19 @@
1
+ from ..constants.aliases import (
2
+ ALIAS_D2EPI as ALIAS_D2EPI,
3
+ ALIAS_DNFR as ALIAS_DNFR,
4
+ ALIAS_DSI as ALIAS_DSI,
5
+ ALIAS_EPI as ALIAS_EPI,
6
+ ALIAS_SI as ALIAS_SI,
7
+ ALIAS_THETA as ALIAS_THETA,
8
+ ALIAS_VF as ALIAS_VF,
9
+ )
10
+
11
+ __all__ = [
12
+ "ALIAS_VF",
13
+ "ALIAS_DNFR",
14
+ "ALIAS_EPI",
15
+ "ALIAS_SI",
16
+ "ALIAS_THETA",
17
+ "ALIAS_D2EPI",
18
+ "ALIAS_DSI",
19
+ ]
@@ -0,0 +1,232 @@
1
+ """Bifurcation dynamics and structural path selection for TNFR operators.
2
+
3
+ This module provides utilities for detecting bifurcation readiness and
4
+ determining viable structural reorganization paths after OZ-induced dissonance.
5
+
6
+ According to TNFR canonical theory (§2.3.3, R4), when ∂²EPI/∂t² > τ,
7
+ the system enters a bifurcation state enabling multiple reorganization
8
+ trajectories. This module implements path selection based on nodal state.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import TYPE_CHECKING
14
+
15
+ if TYPE_CHECKING:
16
+ from ..types import Glyph, NodeId, TNFRGraph
17
+
18
+ from ..alias import get_attr
19
+ from ..constants.aliases import ALIAS_DNFR, ALIAS_EPI, ALIAS_VF
20
+ from ..types import Glyph
21
+
22
+ __all__ = [
23
+ "get_bifurcation_paths",
24
+ "compute_bifurcation_score",
25
+ ]
26
+
27
+
28
+ def get_bifurcation_paths(G: "TNFRGraph", node: "NodeId") -> list["Glyph"]:
29
+ """Return viable structural paths after OZ-induced bifurcation.
30
+
31
+ When OZ (Dissonance) creates bifurcation readiness (∂²EPI/∂t² > τ),
32
+ this function determines which operators can resolve the dissonance
33
+ based on current nodal state.
34
+
35
+ Parameters
36
+ ----------
37
+ G : TNFRGraph
38
+ Graph containing the node
39
+ node : NodeId
40
+ Node identifier
41
+
42
+ Returns
43
+ -------
44
+ list[Glyph]
45
+ List of viable operator glyphs for structural reorganization.
46
+ Empty list if node is not in bifurcation state.
47
+
48
+ Notes
49
+ -----
50
+ **Canonical bifurcation paths:**
51
+
52
+ - **ZHIR (Mutation)**: Viable if νf > 0.8 (sufficient for controlled transformation)
53
+ - **NUL (Contraction)**: Viable if EPI < 0.5 (safe collapse window)
54
+ - **IL (Coherence)**: Always viable (universal resolution path)
55
+ - **THOL (Self-organization)**: Viable if degree >= 2 (network support)
56
+
57
+ The node must have `_bifurcation_ready = True` flag, typically set by
58
+ OZ precondition validation when ∂²EPI/∂t² exceeds threshold τ.
59
+
60
+ Examples
61
+ --------
62
+ >>> from tnfr.structural import create_nfr
63
+ >>> from tnfr.operators.definitions import Dissonance
64
+ >>> from tnfr.dynamics.bifurcation import get_bifurcation_paths
65
+ >>> G, node = create_nfr("test", epi=0.4, vf=1.0)
66
+ >>> # Set up bifurcation conditions
67
+ >>> G.nodes[node]["epi_history"] = [0.2, 0.35, 0.55]
68
+ >>> Dissonance()(G, node, validate_preconditions=True)
69
+ >>> paths = get_bifurcation_paths(G, node)
70
+ >>> # Returns viable operators: [ZHIR, NUL, IL, THOL] or subset
71
+
72
+ See Also
73
+ --------
74
+ tnfr.operators.preconditions.validate_dissonance : Sets bifurcation_ready flag
75
+ tnfr.operators.definitions.SelfOrganization : Spawns sub-EPIs on bifurcation
76
+ """
77
+ # Check if bifurcation active
78
+ if not G.nodes[node].get("_bifurcation_ready", False):
79
+ return [] # No bifurcation active
80
+
81
+ # Get node state for path evaluation
82
+ dnfr = abs(float(get_attr(G.nodes[node], ALIAS_DNFR, 0.0)))
83
+ epi = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
84
+ vf = float(get_attr(G.nodes[node], ALIAS_VF, 0.0))
85
+ degree = G.degree(node)
86
+
87
+ paths = []
88
+
89
+ # ZHIR (Mutation) viable if sufficient νf for controlled transformation
90
+ zhir_threshold = float(G.graph.get("ZHIR_BIFURCATION_VF_THRESHOLD", 0.8))
91
+ if vf > zhir_threshold:
92
+ paths.append(Glyph.ZHIR)
93
+
94
+ # NUL (Contraction) viable if EPI low enough for safe collapse
95
+ nul_threshold = float(G.graph.get("NUL_BIFURCATION_EPI_THRESHOLD", 0.5))
96
+ if epi < nul_threshold:
97
+ paths.append(Glyph.NUL)
98
+
99
+ # IL (Coherence) always viable as universal resolution path
100
+ paths.append(Glyph.IL)
101
+
102
+ # THOL (Self-organization) viable if network connectivity supports it
103
+ thol_min_degree = int(G.graph.get("THOL_BIFURCATION_MIN_DEGREE", 2))
104
+ if degree >= thol_min_degree:
105
+ paths.append(Glyph.THOL)
106
+
107
+ return paths
108
+
109
+
110
+ def compute_bifurcation_score(
111
+ d2epi: float,
112
+ dnfr: float,
113
+ vf: float,
114
+ epi: float,
115
+ tau: float = 0.5,
116
+ ) -> float:
117
+ """Compute quantitative bifurcation potential [0,1].
118
+
119
+ Integrates multiple structural indicators to assess bifurcation readiness.
120
+ According to TNFR canonical theory (§2.3.3, R4), bifurcation occurs when
121
+ ∂²EPI/∂t² > τ (acceleration exceeds threshold). This function extends that
122
+ binary condition into a continuous score that accounts for multiple factors.
123
+
124
+ Parameters
125
+ ----------
126
+ d2epi : float
127
+ Structural acceleration (∂²EPI/∂t²). Primary indicator of bifurcation.
128
+ When |d2epi| > τ, the system enters a bifurcation state enabling
129
+ multiple reorganization trajectories.
130
+ dnfr : float
131
+ Internal reorganization operator (ΔNFR). Magnitude indicates instability
132
+ level. Higher |ΔNFR| means stronger reorganization pressure.
133
+ vf : float
134
+ Structural frequency (νf) in Hz_str units. Determines capacity to respond
135
+ to bifurcation. Higher νf enables faster reorganization along new paths.
136
+ epi : float
137
+ Primary Information Structure. Provides structural substrate for
138
+ bifurcation. Higher EPI indicates more material to reorganize.
139
+ tau : float, default 0.5
140
+ Bifurcation acceleration threshold. When |d2epi| > tau, bifurcation
141
+ becomes active. Default 0.5 is the canonical TNFR threshold.
142
+
143
+ Returns
144
+ -------
145
+ float
146
+ Bifurcation score in range [0.0, 1.0]:
147
+ - 0.0 = no bifurcation potential (stable)
148
+ - 0.5 = bifurcation threshold (critical)
149
+ - 1.0 = maximal bifurcation readiness (multiple paths viable)
150
+
151
+ Notes
152
+ -----
153
+ The bifurcation score is a weighted combination of four factors:
154
+
155
+ 1. **Acceleration factor** (40%): |∂²EPI/∂t²| / τ
156
+ Primary indicator. Measures how close the system is to or beyond
157
+ the bifurcation threshold.
158
+
159
+ 2. **Instability factor** (30%): |ΔNFR|
160
+ Secondary indicator. Measures reorganization pressure that drives
161
+ bifurcation exploration.
162
+
163
+ 3. **Capacity factor** (20%): νf / 2.0
164
+ Measures structural reorganization capacity. Higher νf enables faster
165
+ response to bifurcation opportunities.
166
+
167
+ 4. **Substrate factor** (10%): EPI / 0.8
168
+ Measures available structural material. Higher EPI provides more
169
+ degrees of freedom for bifurcation paths.
170
+
171
+ Formula:
172
+ score = 0.4 * accel + 0.3 * instability + 0.2 * capacity + 0.1 * substrate
173
+
174
+ All factors are normalized to [0, 1] and clipped before combination.
175
+
176
+ Examples
177
+ --------
178
+ >>> from tnfr.dynamics.bifurcation import compute_bifurcation_score
179
+ >>>
180
+ >>> # Low bifurcation potential (stable state)
181
+ >>> score = compute_bifurcation_score(
182
+ ... d2epi=0.1, # Low acceleration
183
+ ... dnfr=0.05, # Low instability
184
+ ... vf=0.5, # Moderate capacity
185
+ ... epi=0.3, # Low substrate
186
+ ... )
187
+ >>> assert score < 0.3 # Low score
188
+ >>>
189
+ >>> # High bifurcation potential (critical state)
190
+ >>> score = compute_bifurcation_score(
191
+ ... d2epi=0.7, # High acceleration (> tau)
192
+ ... dnfr=0.6, # High instability
193
+ ... vf=1.8, # High capacity
194
+ ... epi=0.7, # High substrate
195
+ ... )
196
+ >>> assert score > 0.7 # High score
197
+
198
+ See Also
199
+ --------
200
+ get_bifurcation_paths : Determine viable operators after bifurcation
201
+ tnfr.operators.metrics.dissonance_metrics : Uses score in OZ metrics
202
+ """
203
+ from ..utils import get_numpy
204
+
205
+ np = get_numpy()
206
+
207
+ # 1. Acceleration factor (primary indicator)
208
+ # Normalized by tau threshold
209
+ accel_factor = min(abs(d2epi) / tau, 1.0) if tau > 0 else 0.0
210
+
211
+ # 2. Instability factor (secondary indicator)
212
+ # Already dimensionless, clip to [0, 1]
213
+ instability_factor = min(abs(dnfr), 1.0)
214
+
215
+ # 3. Capacity factor (reorganization capability)
216
+ # Normalize by 2.0 (typical high νf value)
217
+ capacity_factor = min(vf / 2.0, 1.0) if vf >= 0 else 0.0
218
+
219
+ # 4. Substrate factor (structural material available)
220
+ # Normalize by 0.8 (typical high EPI value)
221
+ substrate_factor = min(epi / 0.8, 1.0) if epi >= 0 else 0.0
222
+
223
+ # Weighted combination (percentages sum to 100%)
224
+ score = (
225
+ 0.4 * accel_factor # 40% - primary
226
+ + 0.3 * instability_factor # 30% - secondary
227
+ + 0.2 * capacity_factor # 20% - capability
228
+ + 0.1 * substrate_factor # 10% - material
229
+ )
230
+
231
+ # Ensure result is in [0, 1] range
232
+ return float(np.clip(score, 0.0, 1.0))