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,129 @@
1
+ from __future__ import annotations
2
+
3
+ from .._compat import TypeAlias as TypeAlias
4
+ from ..alias import (
5
+ collect_attr as collect_attr,
6
+ collect_theta_attr as collect_theta_attr,
7
+ get_attr as get_attr,
8
+ set_attr as set_attr,
9
+ )
10
+ from ..constants import get_param as get_param
11
+ from ..constants.aliases import (
12
+ ALIAS_D2VF as ALIAS_D2VF,
13
+ ALIAS_DEPI as ALIAS_DEPI,
14
+ ALIAS_DNFR as ALIAS_DNFR,
15
+ ALIAS_DSI as ALIAS_DSI,
16
+ ALIAS_DVF as ALIAS_DVF,
17
+ ALIAS_EPI as ALIAS_EPI,
18
+ ALIAS_SI as ALIAS_SI,
19
+ ALIAS_VF as ALIAS_VF,
20
+ )
21
+ from ..glyph_history import (
22
+ append_metric as append_metric,
23
+ ensure_history as ensure_history,
24
+ )
25
+ from ..observers import (
26
+ DEFAULT_GLYPH_LOAD_SPAN as DEFAULT_GLYPH_LOAD_SPAN,
27
+ DEFAULT_WBAR_SPAN as DEFAULT_WBAR_SPAN,
28
+ glyph_load as glyph_load,
29
+ kuramoto_order as kuramoto_order,
30
+ phase_sync as phase_sync,
31
+ )
32
+ from ..sense import sigma_vector as sigma_vector
33
+ from ..types import (
34
+ CoherenceMetric as CoherenceMetric,
35
+ FloatArray as FloatArray,
36
+ FloatMatrix as FloatMatrix,
37
+ GlyphLoadDistribution as GlyphLoadDistribution,
38
+ HistoryState as HistoryState,
39
+ NodeId as NodeId,
40
+ ParallelWijPayload as ParallelWijPayload,
41
+ SigmaVector as SigmaVector,
42
+ TNFRGraph as TNFRGraph,
43
+ )
44
+ from ..utils import (
45
+ CallbackEvent as CallbackEvent,
46
+ callback_manager as callback_manager,
47
+ clamp01 as clamp01,
48
+ ensure_node_index_map as ensure_node_index_map,
49
+ get_logger as get_logger,
50
+ get_numpy as get_numpy,
51
+ normalize_weights as normalize_weights,
52
+ resolve_chunk_size as resolve_chunk_size,
53
+ )
54
+ from .common import (
55
+ compute_coherence as compute_coherence,
56
+ min_max_range as min_max_range,
57
+ )
58
+ from .trig_cache import (
59
+ compute_theta_trig as compute_theta_trig,
60
+ get_trig_cache as get_trig_cache,
61
+ )
62
+ from _typeshed import Incomplete
63
+ from collections.abc import Callable, Mapping, Sequence
64
+ from dataclasses import dataclass
65
+ from types import ModuleType
66
+ from typing import Any
67
+
68
+ logger: Incomplete
69
+ GLYPH_LOAD_STABILIZERS_KEY: str
70
+
71
+ @dataclass
72
+ class SimilarityInputs:
73
+ th_vals: Sequence[float]
74
+ epi_vals: Sequence[float]
75
+ vf_vals: Sequence[float]
76
+ si_vals: Sequence[float]
77
+ cos_vals: Sequence[float] | None = ...
78
+ sin_vals: Sequence[float] | None = ...
79
+
80
+ CoherenceMatrixDense = list[list[float]]
81
+ CoherenceMatrixSparse = list[tuple[int, int, float]]
82
+ CoherenceMatrixPayload = CoherenceMatrixDense | CoherenceMatrixSparse
83
+ PhaseSyncWeights: TypeAlias
84
+ SimilarityComponents = tuple[float, float, float, float]
85
+ VectorizedComponents: TypeAlias
86
+ ScalarOrArray: TypeAlias
87
+ StabilityChunkArgs = tuple[
88
+ Sequence[float],
89
+ Sequence[float],
90
+ Sequence[float],
91
+ Sequence[float | None],
92
+ Sequence[float],
93
+ Sequence[float | None],
94
+ Sequence[float | None],
95
+ float,
96
+ float,
97
+ float,
98
+ ]
99
+ StabilityChunkResult = tuple[
100
+ int, int, float, float, list[float], list[float], list[float]
101
+ ]
102
+ MetricValue: TypeAlias
103
+ MetricProvider = Callable[[], MetricValue]
104
+ MetricRecord: TypeAlias
105
+
106
+ def compute_wij_phase_epi_vf_si(
107
+ inputs: SimilarityInputs,
108
+ i: int | None = None,
109
+ j: int | None = None,
110
+ *,
111
+ trig: Any | None = None,
112
+ G: TNFRGraph | None = None,
113
+ nodes: Sequence[NodeId] | None = None,
114
+ epi_range: float = 1.0,
115
+ vf_range: float = 1.0,
116
+ np: ModuleType | None = None,
117
+ ) -> SimilarityComponents | VectorizedComponents: ...
118
+ def coherence_matrix(
119
+ G: TNFRGraph, use_numpy: bool | None = None, *, n_jobs: int | None = None
120
+ ) -> tuple[list[NodeId] | None, CoherenceMatrixPayload | None]: ...
121
+ def local_phase_sync_weighted(
122
+ G: TNFRGraph,
123
+ n: NodeId,
124
+ nodes_order: Sequence[NodeId] | None = None,
125
+ W_row: PhaseSyncWeights | None = None,
126
+ node_to_index: Mapping[NodeId, int] | None = None,
127
+ ) -> float: ...
128
+ def local_phase_sync(G: TNFRGraph, n: NodeId) -> float: ...
129
+ def register_coherence_callbacks(G: TNFRGraph) -> None: ...
tnfr/metrics/common.py ADDED
@@ -0,0 +1,158 @@
1
+ """Shared helpers for TNFR metrics."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from types import MappingProxyType
6
+ from typing import Any, Iterable, Mapping, Sequence
7
+
8
+ from ..alias import collect_attr, get_attr, multi_recompute_abs_max
9
+ from ..constants import DEFAULTS
10
+ from ..constants.aliases import ALIAS_D2EPI, ALIAS_DEPI, ALIAS_DNFR, ALIAS_VF
11
+ from ..utils import clamp01, kahan_sum_nd, normalize_optional_int
12
+ from ..types import GraphLike, NodeAttrMap
13
+ from ..utils import edge_version_cache, get_numpy, normalize_weights
14
+
15
+ __all__ = (
16
+ "GraphLike",
17
+ "compute_coherence",
18
+ "compute_dnfr_accel_max",
19
+ "normalize_dnfr",
20
+ "ensure_neighbors_map",
21
+ "merge_graph_weights",
22
+ "merge_and_normalize_weights",
23
+ "min_max_range",
24
+ "_coerce_jobs",
25
+ "_get_vf_dnfr_max",
26
+ )
27
+
28
+
29
+ def compute_coherence(
30
+ G: GraphLike, *, return_means: bool = False
31
+ ) -> float | tuple[float, float, float]:
32
+ """Compute global coherence ``C`` from ``ΔNFR`` and ``dEPI``."""
33
+
34
+ count = G.number_of_nodes()
35
+ if count == 0:
36
+ return (0.0, 0.0, 0.0) if return_means else 0.0
37
+
38
+ nodes = G.nodes
39
+ np = get_numpy()
40
+ dnfr_values = collect_attr(G, nodes, ALIAS_DNFR, 0.0, np=np)
41
+ depi_values = collect_attr(G, nodes, ALIAS_DEPI, 0.0, np=np)
42
+
43
+ if np is not None:
44
+ dnfr_mean = float(np.mean(np.abs(dnfr_values)))
45
+ depi_mean = float(np.mean(np.abs(depi_values)))
46
+ else:
47
+ dnfr_sum, depi_sum = kahan_sum_nd(
48
+ ((abs(d), abs(e)) for d, e in zip(dnfr_values, depi_values)),
49
+ dims=2,
50
+ )
51
+ dnfr_mean = dnfr_sum / count
52
+ depi_mean = depi_sum / count
53
+
54
+ coherence = 1.0 / (1.0 + dnfr_mean + depi_mean)
55
+ return (coherence, dnfr_mean, depi_mean) if return_means else coherence
56
+
57
+
58
+ def ensure_neighbors_map(G: GraphLike) -> Mapping[Any, Sequence[Any]]:
59
+ """Return cached neighbors list keyed by node as a read-only mapping."""
60
+
61
+ def builder() -> Mapping[Any, Sequence[Any]]:
62
+ return MappingProxyType({n: tuple(G.neighbors(n)) for n in G})
63
+
64
+ return edge_version_cache(G, "_neighbors", builder)
65
+
66
+
67
+ def merge_graph_weights(G: GraphLike, key: str) -> dict[str, float]:
68
+ """Merge default weights for ``key`` with any graph overrides."""
69
+
70
+ overrides = G.graph.get(key, {})
71
+ if overrides is None or not isinstance(overrides, Mapping):
72
+ overrides = {}
73
+ return {**DEFAULTS[key], **overrides}
74
+
75
+
76
+ def merge_and_normalize_weights(
77
+ G: GraphLike,
78
+ key: str,
79
+ fields: Sequence[str],
80
+ *,
81
+ default: float = 0.0,
82
+ ) -> dict[str, float]:
83
+ """Merge defaults for ``key`` and normalise ``fields``."""
84
+
85
+ w = merge_graph_weights(G, key)
86
+ return normalize_weights(
87
+ w,
88
+ fields,
89
+ default=default,
90
+ error_on_conversion=False,
91
+ error_on_negative=False,
92
+ warn_once=True,
93
+ )
94
+
95
+
96
+ def compute_dnfr_accel_max(G: GraphLike) -> dict[str, float]:
97
+ """Compute absolute maxima of |ΔNFR| and |d²EPI/dt²|."""
98
+
99
+ return multi_recompute_abs_max(
100
+ G, {"dnfr_max": ALIAS_DNFR, "accel_max": ALIAS_D2EPI}
101
+ )
102
+
103
+
104
+ def normalize_dnfr(nd: NodeAttrMap, max_val: float) -> float:
105
+ """Normalise ``|ΔNFR|`` using ``max_val``."""
106
+
107
+ if max_val <= 0:
108
+ return 0.0
109
+ val = abs(get_attr(nd, ALIAS_DNFR, 0.0))
110
+ return clamp01(val / max_val)
111
+
112
+
113
+ def min_max_range(
114
+ values: Iterable[float], *, default: tuple[float, float] = (0.0, 0.0)
115
+ ) -> tuple[float, float]:
116
+ """Return the minimum and maximum values observed in ``values``."""
117
+
118
+ it = iter(values)
119
+ try:
120
+ first = next(it)
121
+ except StopIteration:
122
+ return default
123
+ min_val = max_val = first
124
+ for val in it:
125
+ if val < min_val:
126
+ min_val = val
127
+ elif val > max_val:
128
+ max_val = val
129
+ return min_val, max_val
130
+
131
+
132
+ def _get_vf_dnfr_max(G: GraphLike) -> tuple[float, float]:
133
+ """Ensure and return absolute maxima for ``νf`` and ``ΔNFR``."""
134
+
135
+ vfmax = G.graph.get("_vfmax")
136
+ dnfrmax = G.graph.get("_dnfrmax")
137
+ if vfmax is None or dnfrmax is None:
138
+ maxes = multi_recompute_abs_max(G, {"_vfmax": ALIAS_VF, "_dnfrmax": ALIAS_DNFR})
139
+ if vfmax is None:
140
+ vfmax = maxes["_vfmax"]
141
+ if dnfrmax is None:
142
+ dnfrmax = maxes["_dnfrmax"]
143
+ G.graph["_vfmax"] = vfmax
144
+ G.graph["_dnfrmax"] = dnfrmax
145
+ vfmax = 1.0 if vfmax == 0 else vfmax
146
+ dnfrmax = 1.0 if dnfrmax == 0 else dnfrmax
147
+ return float(vfmax), float(dnfrmax)
148
+
149
+
150
+ def _coerce_jobs(raw_jobs: Any | None) -> int | None:
151
+ """Normalise parallel job hints shared by metrics modules."""
152
+
153
+ return normalize_optional_int(
154
+ raw_jobs,
155
+ allow_non_positive=False,
156
+ strict=False,
157
+ sentinels=None,
158
+ )
@@ -0,0 +1,35 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterable, Mapping, Sequence
4
+ from typing import Any, Literal, overload
5
+
6
+ from ..types import GraphLike, NodeAttrMap
7
+
8
+ __all__: tuple[str, ...]
9
+
10
+ def __getattr__(name: str) -> Any: ...
11
+ @overload
12
+ def compute_coherence(G: GraphLike, *, return_means: Literal[False] = ...) -> float: ...
13
+ @overload
14
+ def compute_coherence(
15
+ G: GraphLike, *, return_means: Literal[True]
16
+ ) -> tuple[float, float, float]: ...
17
+ def compute_coherence(
18
+ G: GraphLike, *, return_means: bool = ...
19
+ ) -> float | tuple[float, float, float]: ...
20
+ def ensure_neighbors_map(G: GraphLike) -> Mapping[Any, Sequence[Any]]: ...
21
+ def merge_graph_weights(G: GraphLike, key: str) -> dict[str, float]: ...
22
+ def merge_and_normalize_weights(
23
+ G: GraphLike,
24
+ key: str,
25
+ fields: Sequence[str],
26
+ *,
27
+ default: float = ...,
28
+ ) -> dict[str, float]: ...
29
+ def compute_dnfr_accel_max(G: GraphLike) -> dict[str, float]: ...
30
+ def normalize_dnfr(nd: NodeAttrMap, max_val: float) -> float: ...
31
+ def min_max_range(
32
+ values: Iterable[float], *, default: tuple[float, float] = ...
33
+ ) -> tuple[float, float]: ...
34
+ def _get_vf_dnfr_max(G: GraphLike) -> tuple[float, float]: ...
35
+ def _coerce_jobs(raw_jobs: Any | None) -> int | None: ...
tnfr/metrics/core.py ADDED
@@ -0,0 +1,316 @@
1
+ """Basic metrics orchestrator."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping, MutableMapping
6
+ from typing import Any, NamedTuple, cast
7
+
8
+ from ..utils import CallbackEvent, callback_manager
9
+ from ..constants import get_param
10
+ from ..glyph_history import append_metric, ensure_history
11
+ from ..telemetry import ensure_nu_f_telemetry
12
+ from ..units import get_hz_bridge
13
+ from ..telemetry.verbosity import (
14
+ TELEMETRY_VERBOSITY_DEFAULT,
15
+ TELEMETRY_VERBOSITY_LEVELS,
16
+ TelemetryVerbosity,
17
+ )
18
+ from ..types import (
19
+ GlyphSelector,
20
+ NodeId,
21
+ SelectorPreselectionChoices,
22
+ SelectorPreselectionMetrics,
23
+ SelectorPreselectionPayload,
24
+ TNFRGraph,
25
+ TraceCallback,
26
+ TraceFieldFn,
27
+ TraceFieldMap,
28
+ TraceFieldRegistry,
29
+ )
30
+ from ..utils import get_logger
31
+ from .coherence import (
32
+ GLYPH_LOAD_STABILIZERS_KEY,
33
+ _aggregate_si,
34
+ _track_stability,
35
+ _update_coherence,
36
+ _update_phase_sync,
37
+ _update_sigma,
38
+ register_coherence_callbacks,
39
+ )
40
+ from .diagnosis import register_diagnosis_callbacks
41
+ from .glyph_timing import GlyphMetricsHistory, _compute_advanced_metrics
42
+ from .reporting import (
43
+ Tg_by_node,
44
+ Tg_global,
45
+ glyph_top,
46
+ glyphogram_series,
47
+ latency_series,
48
+ )
49
+
50
+ logger = get_logger(__name__)
51
+
52
+ __all__ = [
53
+ "TNFRGraph",
54
+ "NodeId",
55
+ "GlyphSelector",
56
+ "SelectorPreselectionMetrics",
57
+ "SelectorPreselectionChoices",
58
+ "SelectorPreselectionPayload",
59
+ "TraceCallback",
60
+ "TraceFieldFn",
61
+ "TraceFieldMap",
62
+ "TraceFieldRegistry",
63
+ "_metrics_step",
64
+ "register_metrics_callbacks",
65
+ "Tg_global",
66
+ "Tg_by_node",
67
+ "latency_series",
68
+ "glyphogram_series",
69
+ "glyph_top",
70
+ ]
71
+
72
+
73
+ class MetricsVerbositySpec(NamedTuple):
74
+ """Runtime configuration for metrics verbosity tiers."""
75
+
76
+ name: str
77
+ enable_phase_sync: bool
78
+ enable_sigma: bool
79
+ enable_aggregate_si: bool
80
+ enable_advanced: bool
81
+ attach_coherence_hooks: bool
82
+ attach_diagnosis_hooks: bool
83
+ enable_nu_f: bool
84
+
85
+
86
+ METRICS_VERBOSITY_DEFAULT = TELEMETRY_VERBOSITY_DEFAULT
87
+
88
+ _METRICS_VERBOSITY_PRESETS: dict[str, MetricsVerbositySpec] = {}
89
+
90
+
91
+ def _register_metrics_preset(spec: MetricsVerbositySpec) -> None:
92
+ if spec.name not in TELEMETRY_VERBOSITY_LEVELS:
93
+ raise ValueError(
94
+ "Unknown metrics verbosity '%s'; use %s"
95
+ % (
96
+ spec.name,
97
+ ", ".join(TELEMETRY_VERBOSITY_LEVELS),
98
+ )
99
+ )
100
+ _METRICS_VERBOSITY_PRESETS[spec.name] = spec
101
+
102
+
103
+ _register_metrics_preset(
104
+ MetricsVerbositySpec(
105
+ name=TelemetryVerbosity.BASIC.value,
106
+ enable_phase_sync=False,
107
+ enable_sigma=False,
108
+ enable_aggregate_si=False,
109
+ enable_advanced=False,
110
+ attach_coherence_hooks=False,
111
+ attach_diagnosis_hooks=False,
112
+ enable_nu_f=False,
113
+ )
114
+ )
115
+
116
+ _detailed_spec = MetricsVerbositySpec(
117
+ name=TelemetryVerbosity.DETAILED.value,
118
+ enable_phase_sync=True,
119
+ enable_sigma=True,
120
+ enable_aggregate_si=True,
121
+ enable_advanced=False,
122
+ attach_coherence_hooks=True,
123
+ attach_diagnosis_hooks=False,
124
+ enable_nu_f=True,
125
+ )
126
+ _register_metrics_preset(_detailed_spec)
127
+ _register_metrics_preset(
128
+ _detailed_spec._replace(
129
+ name=TelemetryVerbosity.DEBUG.value,
130
+ enable_advanced=True,
131
+ attach_diagnosis_hooks=True,
132
+ enable_nu_f=True,
133
+ )
134
+ )
135
+
136
+ _METRICS_BASE_HISTORY_KEYS = ("C_steps", "stable_frac", "delta_Si", "B")
137
+ _METRICS_PHASE_HISTORY_KEYS = ("phase_sync", "kuramoto_R")
138
+ _METRICS_SIGMA_HISTORY_KEYS = (
139
+ GLYPH_LOAD_STABILIZERS_KEY,
140
+ "glyph_load_disr",
141
+ "sense_sigma_x",
142
+ "sense_sigma_y",
143
+ "sense_sigma_mag",
144
+ "sense_sigma_angle",
145
+ )
146
+ _METRICS_SI_HISTORY_KEYS = ("Si_mean", "Si_hi_frac", "Si_lo_frac")
147
+ _METRICS_NU_F_HISTORY_KEYS = (
148
+ "nu_f_rate_hz_str",
149
+ "nu_f_rate_hz",
150
+ "nu_f_ci_lower_hz_str",
151
+ "nu_f_ci_upper_hz_str",
152
+ "nu_f_ci_lower_hz",
153
+ "nu_f_ci_upper_hz",
154
+ )
155
+
156
+
157
+ def _update_nu_f_snapshot(
158
+ G: TNFRGraph,
159
+ hist: MutableMapping[str, Any],
160
+ *,
161
+ record_history: bool,
162
+ ) -> None:
163
+ """Refresh νf telemetry snapshot and optionally persist it in history."""
164
+
165
+ accumulator = ensure_nu_f_telemetry(G, confidence_level=None)
166
+ snapshot = accumulator.snapshot(graph=G)
167
+ payload = snapshot.as_payload()
168
+ bridge: float | None
169
+ try:
170
+ bridge = float(get_hz_bridge(G))
171
+ except (TypeError, ValueError, KeyError):
172
+ bridge = None
173
+ else:
174
+ payload["hz_bridge"] = bridge
175
+
176
+ telemetry = G.graph.setdefault("telemetry", {})
177
+ if not isinstance(telemetry, MutableMapping):
178
+ telemetry = {}
179
+ G.graph["telemetry"] = telemetry
180
+ telemetry["nu_f_snapshot"] = payload
181
+ telemetry["nu_f_bridge"] = bridge
182
+
183
+ if record_history:
184
+ append_metric(hist, "nu_f_rate_hz_str", snapshot.rate_hz_str)
185
+ append_metric(hist, "nu_f_rate_hz", snapshot.rate_hz)
186
+ append_metric(hist, "nu_f_ci_lower_hz_str", snapshot.ci_lower_hz_str)
187
+ append_metric(hist, "nu_f_ci_upper_hz_str", snapshot.ci_upper_hz_str)
188
+ append_metric(hist, "nu_f_ci_lower_hz", snapshot.ci_lower_hz)
189
+ append_metric(hist, "nu_f_ci_upper_hz", snapshot.ci_upper_hz)
190
+
191
+ G.graph["_nu_f_snapshot_payload"] = payload
192
+
193
+
194
+ def _resolve_metrics_verbosity(cfg: Mapping[str, Any]) -> MetricsVerbositySpec:
195
+ """Return the preset matching ``cfg['verbosity']``."""
196
+
197
+ raw_value = cfg.get("verbosity", METRICS_VERBOSITY_DEFAULT)
198
+ key = str(raw_value).lower()
199
+ spec = _METRICS_VERBOSITY_PRESETS.get(key)
200
+ if spec is not None:
201
+ return spec
202
+ logger.warning(
203
+ "Unknown METRICS verbosity '%s'; falling back to '%s'",
204
+ raw_value,
205
+ METRICS_VERBOSITY_DEFAULT,
206
+ )
207
+ return _METRICS_VERBOSITY_PRESETS[METRICS_VERBOSITY_DEFAULT]
208
+
209
+
210
+ def _metrics_step(G: TNFRGraph, ctx: dict[str, Any] | None = None) -> None:
211
+ """Update operational TNFR metrics per step."""
212
+
213
+ del ctx
214
+
215
+ cfg = cast(Mapping[str, Any], get_param(G, "METRICS"))
216
+ if not cfg.get("enabled", True):
217
+ return
218
+
219
+ spec = _resolve_metrics_verbosity(cfg)
220
+ hist = ensure_history(G)
221
+ if "glyph_load_estab" in hist:
222
+ raise ValueError(
223
+ "History payloads using 'glyph_load_estab' are no longer supported. "
224
+ "Rename the series to 'glyph_load_stabilizers' before loading the graph."
225
+ )
226
+ metrics_sentinel_key = "_metrics_history_id"
227
+ history_id = id(hist)
228
+ if G.graph.get(metrics_sentinel_key) != history_id:
229
+ for key in _METRICS_BASE_HISTORY_KEYS:
230
+ hist.setdefault(key, [])
231
+ if spec.enable_phase_sync:
232
+ for key in _METRICS_PHASE_HISTORY_KEYS:
233
+ hist.setdefault(key, [])
234
+ if spec.enable_sigma:
235
+ for key in _METRICS_SIGMA_HISTORY_KEYS:
236
+ hist.setdefault(key, [])
237
+ if spec.enable_aggregate_si:
238
+ for key in _METRICS_SI_HISTORY_KEYS:
239
+ hist.setdefault(key, [])
240
+ if spec.enable_nu_f:
241
+ for key in _METRICS_NU_F_HISTORY_KEYS:
242
+ hist.setdefault(key, [])
243
+ G.graph[metrics_sentinel_key] = history_id
244
+
245
+ dt = float(get_param(G, "DT"))
246
+ eps_dnfr = float(get_param(G, "EPS_DNFR_STABLE"))
247
+ eps_depi = float(get_param(G, "EPS_DEPI_STABLE"))
248
+ t = float(G.graph.get("_t", 0.0))
249
+
250
+ _update_coherence(G, hist)
251
+
252
+ raw_jobs = cfg.get("n_jobs")
253
+ metrics_jobs: int | None
254
+ try:
255
+ metrics_jobs = None if raw_jobs is None else int(raw_jobs)
256
+ except (TypeError, ValueError):
257
+ metrics_jobs = None
258
+ else:
259
+ if metrics_jobs <= 0:
260
+ metrics_jobs = None
261
+
262
+ _track_stability(
263
+ G,
264
+ hist,
265
+ dt,
266
+ eps_dnfr,
267
+ eps_depi,
268
+ n_jobs=metrics_jobs,
269
+ )
270
+ if spec.enable_phase_sync or spec.enable_sigma:
271
+ try:
272
+ if spec.enable_phase_sync:
273
+ _update_phase_sync(G, hist)
274
+ if spec.enable_sigma:
275
+ _update_sigma(G, hist)
276
+ except (KeyError, AttributeError, TypeError) as exc:
277
+ logger.debug("observer update failed: %s", exc)
278
+
279
+ if hist.get("C_steps") and hist.get("stable_frac"):
280
+ append_metric(
281
+ hist,
282
+ "iota",
283
+ hist["C_steps"][-1] * hist["stable_frac"][-1],
284
+ )
285
+
286
+ if spec.enable_aggregate_si:
287
+ _aggregate_si(G, hist, n_jobs=metrics_jobs)
288
+
289
+ _update_nu_f_snapshot(G, hist, record_history=spec.enable_nu_f)
290
+
291
+ if spec.enable_advanced:
292
+ _compute_advanced_metrics(
293
+ G,
294
+ cast(GlyphMetricsHistory, hist),
295
+ t,
296
+ dt,
297
+ cfg,
298
+ n_jobs=metrics_jobs,
299
+ )
300
+
301
+
302
+ def register_metrics_callbacks(G: TNFRGraph) -> None:
303
+ """Attach canonical metrics callbacks according to graph configuration."""
304
+
305
+ cfg = cast(Mapping[str, Any], get_param(G, "METRICS"))
306
+ spec = _resolve_metrics_verbosity(cfg)
307
+ callback_manager.register_callback(
308
+ G,
309
+ event=CallbackEvent.AFTER_STEP.value,
310
+ func=_metrics_step,
311
+ name="metrics_step",
312
+ )
313
+ if spec.attach_coherence_hooks:
314
+ register_coherence_callbacks(G)
315
+ if spec.attach_diagnosis_hooks:
316
+ register_diagnosis_callbacks(G)
tnfr/metrics/core.pyi ADDED
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ Tg_by_node: Any
8
+ Tg_global: Any
9
+ _metrics_step: Any
10
+ glyph_top: Any
11
+ glyphogram_series: Any
12
+ latency_series: Any
13
+ register_metrics_callbacks: Any