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,238 @@
1
+ """Facade that keeps ΔNFR, νf and phase orchestration coherent across TNFR dynamics.
2
+
3
+ Attributes
4
+ ----------
5
+ run : callable
6
+ Callable that fully manages the evolution loop, integrating the nodal
7
+ equation while enforcing ΔNFR hooks, νf adaptation and phase coordination
8
+ on every step.
9
+ step : callable
10
+ Callable entry point for a single iteration that reuses the
11
+ ΔNFR/νf/phase pipeline while letting callers interleave bespoke telemetry
12
+ or operator injections.
13
+ set_delta_nfr_hook : callable
14
+ Callable used to install custom ΔNFR supervision under
15
+ ``G.graph['compute_delta_nfr']`` so each operator reorganization stays
16
+ coupled to νf drift and phase targets.
17
+ default_glyph_selector, parametric_glyph_selector : AbstractSelector
18
+ Selector implementations that choose glyphs according to ΔNFR trends,
19
+ νf ranges and phase synchrony, ensuring operator firing reinforces
20
+ coherence.
21
+ coordination, dnfr, integrators : module
22
+ Re-exported modules providing explicit control over phase alignment,
23
+ ΔNFR caches and integrator lifecycles to centralize orchestration.
24
+ ProcessPoolExecutor, apply_glyph, compute_Si : callable
25
+ Re-exported utilities for parallel selector evaluation, explicit glyph
26
+ execution and Si telemetry so ΔNFR, νf and phase traces remain observable.
27
+
28
+ Notes
29
+ -----
30
+ The facade aggregates runtime helpers that preserve canonical TNFR dynamics:
31
+ ``dnfr`` manages ΔNFR preparation and caching, ``integrators`` drives the
32
+ numerical updates of νf and EPI, and ``coordination`` synchronizes global and
33
+ local phase. Complementary exports such as
34
+ :func:`~tnfr.dynamics.adaptation.adapt_vf_by_coherence` and
35
+ :func:`~tnfr.dynamics.coordination.coordinate_global_local_phase` allow custom
36
+ feedback loops without breaking operator closure.
37
+
38
+ Examples
39
+ --------
40
+ >>> from tnfr.constants import DNFR_PRIMARY, EPI_PRIMARY, VF_PRIMARY
41
+ >>> from tnfr.structural import Coherence, Emission, Resonance, create_nfr, run_sequence
42
+ >>> from tnfr.dynamics import parametric_glyph_selector, run, set_delta_nfr_hook, step
43
+ >>> G, node = create_nfr("seed", epi=0.22, vf=1.0)
44
+ >>> def regulate_delta(graph, *, n_jobs=None):
45
+ ... for _, nd in graph.nodes(data=True):
46
+ ... delta = nd[VF_PRIMARY] * 0.08
47
+ ... nd[DNFR_PRIMARY] = delta
48
+ ... nd[EPI_PRIMARY] += delta
49
+ ... nd[VF_PRIMARY] += delta * 0.05
50
+ ... return None
51
+ >>> set_delta_nfr_hook(G, regulate_delta, note="ΔNFR guided by νf")
52
+ >>> G.graph["glyph_selector"] = parametric_glyph_selector
53
+ >>> run_sequence(G, node, [Emission(), Resonance(), Coherence()])
54
+ >>> run(G, steps=2, dt=0.05)
55
+ >>> # Automatic integration keeps ΔNFR, νf and phase co-modulated.
56
+ >>> step(G, dt=0.05)
57
+ >>> # Manual control reuses the selector state to consolidate coherence traces.
58
+ """
59
+
60
+ from __future__ import annotations
61
+
62
+ from concurrent.futures import ProcessPoolExecutor
63
+
64
+ from ..metrics.sense_index import compute_Si
65
+ from ..operators import apply_glyph
66
+ from ..types import GlyphCode
67
+ from ..utils import get_numpy
68
+ from . import canonical, coordination, dnfr, integrators, metabolism
69
+ from .adaptation import adapt_vf_by_coherence
70
+ from .bifurcation import get_bifurcation_paths, compute_bifurcation_score
71
+ from .propagation import (
72
+ propagate_dissonance,
73
+ compute_network_dissonance_field,
74
+ detect_bifurcation_cascade,
75
+ )
76
+ from .aliases import (
77
+ ALIAS_D2EPI,
78
+ ALIAS_DNFR,
79
+ ALIAS_DSI,
80
+ ALIAS_EPI,
81
+ ALIAS_SI,
82
+ ALIAS_VF,
83
+ )
84
+ from .canonical import (
85
+ NodalEquationResult,
86
+ compute_canonical_nodal_derivative,
87
+ validate_nodal_gradient,
88
+ validate_structural_frequency,
89
+ )
90
+ from .coordination import coordinate_global_local_phase
91
+ from .dnfr import (
92
+ _compute_dnfr,
93
+ _compute_neighbor_means,
94
+ _init_dnfr_cache,
95
+ _prepare_dnfr_data,
96
+ _refresh_dnfr_vectors,
97
+ default_compute_delta_nfr,
98
+ dnfr_epi_vf_mixed,
99
+ dnfr_laplacian,
100
+ dnfr_phase_only,
101
+ set_delta_nfr_hook,
102
+ )
103
+ from .dynamic_limits import (
104
+ DynamicLimits,
105
+ DynamicLimitsConfig,
106
+ compute_dynamic_limits,
107
+ )
108
+ from .integrators import (
109
+ AbstractIntegrator,
110
+ DefaultIntegrator,
111
+ prepare_integration_params,
112
+ update_epi_via_nodal_equation,
113
+ )
114
+ from .learning import AdaptiveLearningSystem
115
+ from .feedback import StructuralFeedbackLoop
116
+ from .adaptive_sequences import AdaptiveSequenceSelector
117
+ from .homeostasis import StructuralHomeostasis
118
+ from .structural_clip import (
119
+ structural_clip,
120
+ StructuralClipStats,
121
+ get_clip_stats,
122
+ reset_clip_stats,
123
+ )
124
+ from .runtime import (
125
+ _maybe_remesh,
126
+ _normalize_job_overrides,
127
+ _prepare_dnfr,
128
+ _resolve_jobs_override,
129
+ _run_after_callbacks,
130
+ _run_before_callbacks,
131
+ _run_validators,
132
+ _update_epi_hist,
133
+ _update_nodes,
134
+ run,
135
+ step,
136
+ )
137
+ from .sampling import update_node_sample as _update_node_sample
138
+ from .selectors import (
139
+ AbstractSelector,
140
+ DefaultGlyphSelector,
141
+ ParametricGlyphSelector,
142
+ _apply_glyphs,
143
+ _apply_selector,
144
+ _choose_glyph,
145
+ _collect_selector_metrics,
146
+ _configure_selector_weights,
147
+ _prepare_selector_preselection,
148
+ _resolve_preselected_glyph,
149
+ _selector_parallel_jobs,
150
+ _SelectorPreselection,
151
+ default_glyph_selector,
152
+ parametric_glyph_selector,
153
+ )
154
+
155
+ __all__ = (
156
+ "canonical",
157
+ "coordination",
158
+ "dnfr",
159
+ "integrators",
160
+ "metabolism",
161
+ # Bifurcation dynamics
162
+ "get_bifurcation_paths",
163
+ "compute_bifurcation_score",
164
+ # Propagation dynamics
165
+ "propagate_dissonance",
166
+ "compute_network_dissonance_field",
167
+ "detect_bifurcation_cascade",
168
+ "ALIAS_D2EPI",
169
+ "ALIAS_DNFR",
170
+ "ALIAS_DSI",
171
+ "ALIAS_EPI",
172
+ "ALIAS_SI",
173
+ "ALIAS_VF",
174
+ "AbstractSelector",
175
+ "DefaultGlyphSelector",
176
+ "ParametricGlyphSelector",
177
+ "GlyphCode",
178
+ "_SelectorPreselection",
179
+ "_apply_glyphs",
180
+ "_apply_selector",
181
+ "_choose_glyph",
182
+ "_collect_selector_metrics",
183
+ "_configure_selector_weights",
184
+ "ProcessPoolExecutor",
185
+ "_maybe_remesh",
186
+ "_normalize_job_overrides",
187
+ "_prepare_dnfr",
188
+ "_prepare_dnfr_data",
189
+ "_prepare_selector_preselection",
190
+ "_resolve_jobs_override",
191
+ "_resolve_preselected_glyph",
192
+ "_run_after_callbacks",
193
+ "_run_before_callbacks",
194
+ "_run_validators",
195
+ "_selector_parallel_jobs",
196
+ "_update_epi_hist",
197
+ "_update_node_sample",
198
+ "_update_nodes",
199
+ "_compute_dnfr",
200
+ "_compute_neighbor_means",
201
+ "_init_dnfr_cache",
202
+ "_refresh_dnfr_vectors",
203
+ "adapt_vf_by_coherence",
204
+ "coordinate_global_local_phase",
205
+ "compute_Si",
206
+ "compute_canonical_nodal_derivative",
207
+ "NodalEquationResult",
208
+ "validate_nodal_gradient",
209
+ "validate_structural_frequency",
210
+ "default_compute_delta_nfr",
211
+ "default_glyph_selector",
212
+ "dnfr_epi_vf_mixed",
213
+ "dnfr_laplacian",
214
+ "dnfr_phase_only",
215
+ "get_numpy",
216
+ "apply_glyph",
217
+ "parametric_glyph_selector",
218
+ "AbstractIntegrator",
219
+ "DefaultIntegrator",
220
+ "prepare_integration_params",
221
+ "run",
222
+ "set_delta_nfr_hook",
223
+ "step",
224
+ "update_epi_via_nodal_equation",
225
+ "DynamicLimits",
226
+ "DynamicLimitsConfig",
227
+ "compute_dynamic_limits",
228
+ "structural_clip",
229
+ "StructuralClipStats",
230
+ "get_clip_stats",
231
+ "reset_clip_stats",
232
+ "AdaptiveLearningSystem",
233
+ "StructuralFeedbackLoop",
234
+ "AdaptiveSequenceSelector",
235
+ "StructuralHomeostasis",
236
+ "get_bifurcation_paths",
237
+ "compute_bifurcation_score",
238
+ )
@@ -0,0 +1,83 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Literal, Sequence
4
+
5
+ from tnfr.types import GlyphCode, TNFRGraph
6
+
7
+ __all__: tuple[str, ...]
8
+
9
+ dnfr: Any
10
+ integrators: Any
11
+ metabolism: Any
12
+
13
+ ALIAS_D2EPI: Sequence[str]
14
+ ALIAS_DNFR: Sequence[str]
15
+ ALIAS_DSI: Sequence[str]
16
+ ALIAS_EPI: Sequence[str]
17
+ ALIAS_SI: Sequence[str]
18
+ ALIAS_VF: Sequence[str]
19
+
20
+ AbstractSelector: Any
21
+ DefaultGlyphSelector: Any
22
+ ParametricGlyphSelector: Any
23
+ StructuralFeedbackLoop: Any
24
+ AdaptiveSequenceSelector: Any
25
+ StructuralHomeostasis: Any
26
+ AdaptiveLearningSystem: Any
27
+ _SelectorPreselection: Any
28
+ _apply_glyphs: Any
29
+ _apply_selector: Any
30
+ _choose_glyph: Any
31
+ _configure_selector_weights: Any
32
+ ProcessPoolExecutor: Any
33
+ _maybe_remesh: Any
34
+ _normalize_job_overrides: Any
35
+ _prepare_dnfr: Any
36
+ _prepare_dnfr_data: Any
37
+ _prepare_selector_preselection: Any
38
+ _resolve_jobs_override: Any
39
+ _resolve_preselected_glyph: Any
40
+ _run_after_callbacks: Any
41
+ _run_before_callbacks: Any
42
+ _run_validators: Any
43
+ _selector_parallel_jobs: Any
44
+ _update_epi_hist: Any
45
+ _update_node_sample: Any
46
+ _update_nodes: Any
47
+ _compute_dnfr: Any
48
+ _compute_neighbor_means: Any
49
+ _init_dnfr_cache: Any
50
+ _refresh_dnfr_vectors: Any
51
+ adapt_vf_by_coherence: Any
52
+ coordinate_global_local_phase: Any
53
+ default_compute_delta_nfr: Any
54
+ default_glyph_selector: Any
55
+ dnfr_epi_vf_mixed: Any
56
+ dnfr_laplacian: Any
57
+ dnfr_phase_only: Any
58
+ get_numpy: Any
59
+ apply_glyph: Any
60
+ parametric_glyph_selector: Any
61
+
62
+ AbstractIntegrator: Any
63
+ DefaultIntegrator: Any
64
+
65
+ def prepare_integration_params(
66
+ G: TNFRGraph,
67
+ dt: float | None = ...,
68
+ t: float | None = ...,
69
+ method: Literal["euler", "rk4"] | None = ...,
70
+ ) -> tuple[float, int, float, Literal["euler", "rk4"]]: ...
71
+
72
+ run: Any
73
+ set_delta_nfr_hook: Any
74
+ step: Any
75
+
76
+ def update_epi_via_nodal_equation(
77
+ G: TNFRGraph,
78
+ *,
79
+ dt: float | None = ...,
80
+ t: float | None = ...,
81
+ method: Literal["euler", "rk4"] | None = ...,
82
+ n_jobs: int | None = ...,
83
+ ) -> None: ...
@@ -0,0 +1,267 @@
1
+ """νf adaptation routines for TNFR dynamics."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from concurrent.futures import ProcessPoolExecutor
7
+ from typing import Any, cast
8
+
9
+ from ..alias import collect_attr, set_vf
10
+ from ..constants import get_graph_param
11
+ from ..utils import clamp, resolve_chunk_size
12
+ from ..metrics.common import ensure_neighbors_map
13
+ from ..types import CoherenceMetric, DeltaNFR, TNFRGraph
14
+ from ..utils import get_numpy
15
+ from .aliases import ALIAS_DNFR, ALIAS_SI, ALIAS_VF
16
+
17
+ __all__ = ("adapt_vf_by_coherence",)
18
+
19
+
20
+ def _vf_adapt_chunk(
21
+ args: tuple[list[tuple[Any, int, tuple[int, ...]]], tuple[float, ...], float],
22
+ ) -> list[tuple[Any, float]]:
23
+ """Return proposed νf updates for ``chunk`` of stable nodes."""
24
+
25
+ chunk, vf_values, mu = args
26
+ updates: list[tuple[Any, float]] = []
27
+ for node, idx, neighbor_idx in chunk:
28
+ vf = vf_values[idx]
29
+ if neighbor_idx:
30
+ mean = math.fsum(vf_values[j] for j in neighbor_idx) / len(neighbor_idx)
31
+ else:
32
+ mean = vf
33
+ updates.append((node, vf + mu * (mean - vf)))
34
+ return updates
35
+
36
+
37
+ def adapt_vf_by_coherence(G: TNFRGraph, n_jobs: int | None = None) -> None:
38
+ """Synchronise νf to the neighbour mean once ΔNFR and Si stay coherent.
39
+
40
+ Parameters
41
+ ----------
42
+ G : TNFRGraph
43
+ Graph that stores the TNFR nodes and configuration required for
44
+ adaptation. The routine reads ``VF_ADAPT_TAU`` (τ) to decide how many
45
+ consecutive stable steps a node must accumulate in ``stable_count``
46
+ before updating. The adaptation weight ``VF_ADAPT_MU`` (μ) controls how
47
+ quickly νf moves toward the neighbour mean. Stability is detected when
48
+ the absolute ΔNFR stays below ``EPS_DNFR_STABLE`` and the sense index Si
49
+ exceeds the selector threshold ``SELECTOR_THRESHOLDS['si_hi']`` (falling
50
+ back to ``GLYPH_THRESHOLDS['hi']``). Only nodes that satisfy both
51
+ thresholds for τ successive evaluations are eligible for μ-weighted
52
+ averaging.
53
+ n_jobs : int or None, optional
54
+ Number of worker processes used for eligible nodes. ``None`` (the
55
+ default) keeps the adaptation serial, ``1`` disables parallelism, and
56
+ any value greater than one dispatches chunks of nodes to a
57
+ :class:`~concurrent.futures.ProcessPoolExecutor` so large graphs can
58
+ adjust νf without blocking the main dynamic loop.
59
+
60
+ Returns
61
+ -------
62
+ None
63
+ The graph is updated in place; no value is returned.
64
+
65
+ Raises
66
+ ------
67
+ KeyError
68
+ Raised when ``G.graph`` lacks the canonical adaptation parameters and
69
+ defaults have not been injected.
70
+
71
+ Examples
72
+ --------
73
+ >>> from tnfr.constants import inject_defaults
74
+ >>> from tnfr.dynamics import adapt_vf_by_coherence
75
+ >>> from tnfr.structural import create_nfr
76
+ >>> G, seed = create_nfr("seed", vf=0.2)
77
+ >>> _, anchor = create_nfr("anchor", graph=G, vf=1.0)
78
+ >>> G.add_edge(seed, anchor)
79
+ >>> inject_defaults(G)
80
+ >>> G.graph["VF_ADAPT_TAU"] = 2 # τ: consecutive stable steps
81
+ >>> G.graph["VF_ADAPT_MU"] = 0.5 # μ: neighbour coupling strength
82
+ >>> G.graph["SELECTOR_THRESHOLDS"] = {"si_hi": 0.8}
83
+ >>> for node in G.nodes:
84
+ ... G.nodes[node]["Si"] = 0.9 # above ΔSi threshold
85
+ ... G.nodes[node]["ΔNFR"] = 0.0 # within |ΔNFR| ≤ eps guard
86
+ ... G.nodes[node]["stable_count"] = 1
87
+ >>> adapt_vf_by_coherence(G)
88
+ >>> round(G.nodes[seed]["νf"], 2), round(G.nodes[anchor]["νf"], 2)
89
+ (0.6, 0.6)
90
+ >>> G.nodes[seed]["stable_count"], G.nodes[anchor]["stable_count"] >= 2
91
+ (2, True)
92
+ """
93
+
94
+ required_keys = ("VF_ADAPT_TAU", "VF_ADAPT_MU")
95
+ missing_keys = [key for key in required_keys if key not in G.graph]
96
+ if missing_keys:
97
+ missing_list = ", ".join(sorted(missing_keys))
98
+ raise KeyError(
99
+ "adapt_vf_by_coherence requires graph parameters "
100
+ f"{missing_list}; call tnfr.constants.inject_defaults(G) "
101
+ "before adaptation."
102
+ )
103
+
104
+ tau = get_graph_param(G, "VF_ADAPT_TAU", int)
105
+ mu = float(get_graph_param(G, "VF_ADAPT_MU"))
106
+ eps_dnfr = cast(DeltaNFR, get_graph_param(G, "EPS_DNFR_STABLE"))
107
+ thr_sel = get_graph_param(G, "SELECTOR_THRESHOLDS", dict)
108
+ thr_def = get_graph_param(G, "GLYPH_THRESHOLDS", dict)
109
+ si_hi = cast(
110
+ CoherenceMetric,
111
+ float(thr_sel.get("si_hi", thr_def.get("hi", 0.66))),
112
+ )
113
+ vf_min = float(get_graph_param(G, "VF_MIN"))
114
+ vf_max = float(get_graph_param(G, "VF_MAX"))
115
+
116
+ nodes = list(G.nodes)
117
+ if not nodes:
118
+ return
119
+
120
+ neighbors_map = ensure_neighbors_map(G)
121
+ node_count = len(nodes)
122
+ node_index = {node: idx for idx, node in enumerate(nodes)}
123
+
124
+ jobs: int | None
125
+ if n_jobs is None:
126
+ jobs = None
127
+ else:
128
+ try:
129
+ jobs = int(n_jobs)
130
+ except (TypeError, ValueError):
131
+ jobs = None
132
+ else:
133
+ if jobs <= 1:
134
+ jobs = None
135
+
136
+ np_mod = get_numpy()
137
+ use_np = np_mod is not None
138
+
139
+ si_values = collect_attr(G, nodes, ALIAS_SI, 0.0, np=np_mod if use_np else None)
140
+ dnfr_values = collect_attr(G, nodes, ALIAS_DNFR, 0.0, np=np_mod if use_np else None)
141
+ vf_values = collect_attr(G, nodes, ALIAS_VF, 0.0, np=np_mod if use_np else None)
142
+
143
+ if use_np:
144
+ np = np_mod # type: ignore[assignment]
145
+ assert np is not None
146
+ si_arr = si_values.astype(float, copy=False)
147
+ dnfr_arr = np.abs(dnfr_values.astype(float, copy=False))
148
+ vf_arr = vf_values.astype(float, copy=False)
149
+
150
+ prev_counts = np.fromiter(
151
+ (int(G.nodes[node].get("stable_count", 0)) for node in nodes),
152
+ dtype=int,
153
+ count=node_count,
154
+ )
155
+ stable_mask = (si_arr >= si_hi) & (dnfr_arr <= eps_dnfr)
156
+ new_counts = np.where(stable_mask, prev_counts + 1, 0)
157
+
158
+ for node, count in zip(nodes, new_counts.tolist()):
159
+ G.nodes[node]["stable_count"] = int(count)
160
+
161
+ eligible_mask = new_counts >= tau
162
+ if not bool(eligible_mask.any()):
163
+ return
164
+
165
+ max_degree = 0
166
+ if node_count:
167
+ degree_counts = np.fromiter(
168
+ (len(neighbors_map.get(node, ())) for node in nodes),
169
+ dtype=int,
170
+ count=node_count,
171
+ )
172
+ if degree_counts.size:
173
+ max_degree = int(degree_counts.max())
174
+
175
+ if max_degree > 0:
176
+ neighbor_indices = np.zeros((node_count, max_degree), dtype=int)
177
+ mask = np.zeros((node_count, max_degree), dtype=bool)
178
+ for idx, node in enumerate(nodes):
179
+ neigh = neighbors_map.get(node, ())
180
+ if not neigh:
181
+ continue
182
+ idxs = [node_index[nbr] for nbr in neigh if nbr in node_index]
183
+ if not idxs:
184
+ continue
185
+ length = len(idxs)
186
+ neighbor_indices[idx, :length] = idxs
187
+ mask[idx, :length] = True
188
+ neighbor_values = vf_arr[neighbor_indices]
189
+ sums = (neighbor_values * mask).sum(axis=1)
190
+ counts = mask.sum(axis=1)
191
+ neighbor_means = np.where(counts > 0, sums / counts, vf_arr)
192
+ else:
193
+ neighbor_means = vf_arr
194
+
195
+ vf_updates = vf_arr + mu * (neighbor_means - vf_arr)
196
+ for idx in np.nonzero(eligible_mask)[0]:
197
+ node = nodes[int(idx)]
198
+ vf_new = clamp(float(vf_updates[int(idx)]), vf_min, vf_max)
199
+ set_vf(G, node, vf_new)
200
+ return
201
+
202
+ si_list = [float(val) for val in si_values]
203
+ dnfr_list = [abs(float(val)) for val in dnfr_values]
204
+ vf_list = [float(val) for val in vf_values]
205
+
206
+ prev_counts = [int(G.nodes[node].get("stable_count", 0)) for node in nodes]
207
+ stable_flags = [
208
+ si >= si_hi and dnfr <= eps_dnfr for si, dnfr in zip(si_list, dnfr_list)
209
+ ]
210
+ new_counts = [
211
+ prev + 1 if flag else 0 for prev, flag in zip(prev_counts, stable_flags)
212
+ ]
213
+
214
+ for node, count in zip(nodes, new_counts):
215
+ G.nodes[node]["stable_count"] = int(count)
216
+
217
+ eligible_nodes = [node for node, count in zip(nodes, new_counts) if count >= tau]
218
+ if not eligible_nodes:
219
+ return
220
+
221
+ if jobs is None:
222
+ for node in eligible_nodes:
223
+ idx = node_index[node]
224
+ neigh_indices = [
225
+ node_index[nbr]
226
+ for nbr in neighbors_map.get(node, ())
227
+ if nbr in node_index
228
+ ]
229
+ if neigh_indices:
230
+ total = math.fsum(vf_list[i] for i in neigh_indices)
231
+ mean = total / len(neigh_indices)
232
+ else:
233
+ mean = vf_list[idx]
234
+ vf_new = vf_list[idx] + mu * (mean - vf_list[idx])
235
+ set_vf(G, node, clamp(float(vf_new), vf_min, vf_max))
236
+ return
237
+
238
+ work_items: list[tuple[Any, int, tuple[int, ...]]] = []
239
+ for node in eligible_nodes:
240
+ idx = node_index[node]
241
+ neigh_indices = tuple(
242
+ node_index[nbr] for nbr in neighbors_map.get(node, ()) if nbr in node_index
243
+ )
244
+ work_items.append((node, idx, neigh_indices))
245
+
246
+ approx_chunk = math.ceil(len(work_items) / jobs) if jobs else None
247
+ chunk_size = resolve_chunk_size(
248
+ approx_chunk,
249
+ len(work_items),
250
+ minimum=1,
251
+ )
252
+ chunks = [
253
+ work_items[i : i + chunk_size] for i in range(0, len(work_items), chunk_size)
254
+ ]
255
+ vf_tuple = tuple(vf_list)
256
+ updates: dict[Any, float] = {}
257
+ with ProcessPoolExecutor(max_workers=jobs) as executor:
258
+ args = ((chunk, vf_tuple, mu) for chunk in chunks)
259
+ for chunk_updates in executor.map(_vf_adapt_chunk, args):
260
+ for node, value in chunk_updates:
261
+ updates[node] = float(value)
262
+
263
+ for node in eligible_nodes:
264
+ vf_new = updates.get(node)
265
+ if vf_new is None:
266
+ continue
267
+ set_vf(G, node, clamp(float(vf_new), vf_min, vf_max))
@@ -0,0 +1,7 @@
1
+ from __future__ import annotations
2
+
3
+ from ..types import TNFRGraph
4
+
5
+ __all__ = ["adapt_vf_by_coherence"]
6
+
7
+ def adapt_vf_by_coherence(G: TNFRGraph, n_jobs: int | None = None) -> None: ...