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

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

Potentially problematic release.


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

Files changed (365) hide show
  1. tnfr/__init__.py +334 -50
  2. tnfr/__init__.pyi +33 -0
  3. tnfr/_compat.py +10 -0
  4. tnfr/_generated_version.py +34 -0
  5. tnfr/_version.py +49 -0
  6. tnfr/_version.pyi +7 -0
  7. tnfr/alias.py +214 -37
  8. tnfr/alias.pyi +108 -0
  9. tnfr/backends/__init__.py +354 -0
  10. tnfr/backends/jax_backend.py +173 -0
  11. tnfr/backends/numpy_backend.py +238 -0
  12. tnfr/backends/optimized_numpy.py +420 -0
  13. tnfr/backends/torch_backend.py +408 -0
  14. tnfr/cache.py +149 -556
  15. tnfr/cache.pyi +13 -0
  16. tnfr/cli/__init__.py +51 -16
  17. tnfr/cli/__init__.pyi +26 -0
  18. tnfr/cli/arguments.py +344 -32
  19. tnfr/cli/arguments.pyi +29 -0
  20. tnfr/cli/execution.py +676 -50
  21. tnfr/cli/execution.pyi +70 -0
  22. tnfr/cli/interactive_validator.py +614 -0
  23. tnfr/cli/utils.py +18 -3
  24. tnfr/cli/utils.pyi +7 -0
  25. tnfr/cli/validate.py +236 -0
  26. tnfr/compat/__init__.py +85 -0
  27. tnfr/compat/dataclass.py +136 -0
  28. tnfr/compat/jsonschema_stub.py +61 -0
  29. tnfr/compat/matplotlib_stub.py +73 -0
  30. tnfr/compat/numpy_stub.py +155 -0
  31. tnfr/config/__init__.py +224 -0
  32. tnfr/config/__init__.pyi +10 -0
  33. tnfr/{constants_glyphs.py → config/constants.py} +26 -20
  34. tnfr/config/constants.pyi +12 -0
  35. tnfr/config/defaults.py +54 -0
  36. tnfr/{constants/core.py → config/defaults_core.py} +59 -6
  37. tnfr/config/defaults_init.py +33 -0
  38. tnfr/config/defaults_metric.py +104 -0
  39. tnfr/config/feature_flags.py +81 -0
  40. tnfr/config/feature_flags.pyi +16 -0
  41. tnfr/config/glyph_constants.py +31 -0
  42. tnfr/config/init.py +77 -0
  43. tnfr/config/init.pyi +8 -0
  44. tnfr/config/operator_names.py +254 -0
  45. tnfr/config/operator_names.pyi +36 -0
  46. tnfr/config/physics_derivation.py +354 -0
  47. tnfr/config/presets.py +83 -0
  48. tnfr/config/presets.pyi +7 -0
  49. tnfr/config/security.py +927 -0
  50. tnfr/config/thresholds.py +114 -0
  51. tnfr/config/tnfr_config.py +498 -0
  52. tnfr/constants/__init__.py +51 -133
  53. tnfr/constants/__init__.pyi +92 -0
  54. tnfr/constants/aliases.py +33 -0
  55. tnfr/constants/aliases.pyi +27 -0
  56. tnfr/constants/init.py +3 -1
  57. tnfr/constants/init.pyi +12 -0
  58. tnfr/constants/metric.py +9 -15
  59. tnfr/constants/metric.pyi +19 -0
  60. tnfr/core/__init__.py +33 -0
  61. tnfr/core/container.py +226 -0
  62. tnfr/core/default_implementations.py +329 -0
  63. tnfr/core/interfaces.py +279 -0
  64. tnfr/dynamics/__init__.py +213 -633
  65. tnfr/dynamics/__init__.pyi +83 -0
  66. tnfr/dynamics/adaptation.py +267 -0
  67. tnfr/dynamics/adaptation.pyi +7 -0
  68. tnfr/dynamics/adaptive_sequences.py +189 -0
  69. tnfr/dynamics/adaptive_sequences.pyi +14 -0
  70. tnfr/dynamics/aliases.py +23 -0
  71. tnfr/dynamics/aliases.pyi +19 -0
  72. tnfr/dynamics/bifurcation.py +232 -0
  73. tnfr/dynamics/canonical.py +229 -0
  74. tnfr/dynamics/canonical.pyi +48 -0
  75. tnfr/dynamics/coordination.py +385 -0
  76. tnfr/dynamics/coordination.pyi +25 -0
  77. tnfr/dynamics/dnfr.py +2699 -398
  78. tnfr/dynamics/dnfr.pyi +26 -0
  79. tnfr/dynamics/dynamic_limits.py +225 -0
  80. tnfr/dynamics/feedback.py +252 -0
  81. tnfr/dynamics/feedback.pyi +24 -0
  82. tnfr/dynamics/fused_dnfr.py +454 -0
  83. tnfr/dynamics/homeostasis.py +157 -0
  84. tnfr/dynamics/homeostasis.pyi +14 -0
  85. tnfr/dynamics/integrators.py +496 -102
  86. tnfr/dynamics/integrators.pyi +36 -0
  87. tnfr/dynamics/learning.py +310 -0
  88. tnfr/dynamics/learning.pyi +33 -0
  89. tnfr/dynamics/metabolism.py +254 -0
  90. tnfr/dynamics/nbody.py +796 -0
  91. tnfr/dynamics/nbody_tnfr.py +783 -0
  92. tnfr/dynamics/propagation.py +326 -0
  93. tnfr/dynamics/runtime.py +908 -0
  94. tnfr/dynamics/runtime.pyi +77 -0
  95. tnfr/dynamics/sampling.py +10 -5
  96. tnfr/dynamics/sampling.pyi +7 -0
  97. tnfr/dynamics/selectors.py +711 -0
  98. tnfr/dynamics/selectors.pyi +85 -0
  99. tnfr/dynamics/structural_clip.py +207 -0
  100. tnfr/errors/__init__.py +37 -0
  101. tnfr/errors/contextual.py +492 -0
  102. tnfr/execution.py +77 -55
  103. tnfr/execution.pyi +45 -0
  104. tnfr/extensions/__init__.py +205 -0
  105. tnfr/extensions/__init__.pyi +18 -0
  106. tnfr/extensions/base.py +173 -0
  107. tnfr/extensions/base.pyi +35 -0
  108. tnfr/extensions/business/__init__.py +71 -0
  109. tnfr/extensions/business/__init__.pyi +11 -0
  110. tnfr/extensions/business/cookbook.py +88 -0
  111. tnfr/extensions/business/cookbook.pyi +8 -0
  112. tnfr/extensions/business/health_analyzers.py +202 -0
  113. tnfr/extensions/business/health_analyzers.pyi +9 -0
  114. tnfr/extensions/business/patterns.py +183 -0
  115. tnfr/extensions/business/patterns.pyi +8 -0
  116. tnfr/extensions/medical/__init__.py +73 -0
  117. tnfr/extensions/medical/__init__.pyi +11 -0
  118. tnfr/extensions/medical/cookbook.py +88 -0
  119. tnfr/extensions/medical/cookbook.pyi +8 -0
  120. tnfr/extensions/medical/health_analyzers.py +181 -0
  121. tnfr/extensions/medical/health_analyzers.pyi +9 -0
  122. tnfr/extensions/medical/patterns.py +163 -0
  123. tnfr/extensions/medical/patterns.pyi +8 -0
  124. tnfr/flatten.py +29 -50
  125. tnfr/flatten.pyi +21 -0
  126. tnfr/gamma.py +66 -53
  127. tnfr/gamma.pyi +36 -0
  128. tnfr/glyph_history.py +144 -57
  129. tnfr/glyph_history.pyi +35 -0
  130. tnfr/glyph_runtime.py +19 -0
  131. tnfr/glyph_runtime.pyi +8 -0
  132. tnfr/immutable.py +70 -30
  133. tnfr/immutable.pyi +36 -0
  134. tnfr/initialization.py +22 -16
  135. tnfr/initialization.pyi +65 -0
  136. tnfr/io.py +5 -241
  137. tnfr/io.pyi +13 -0
  138. tnfr/locking.pyi +7 -0
  139. tnfr/mathematics/__init__.py +79 -0
  140. tnfr/mathematics/backend.py +453 -0
  141. tnfr/mathematics/backend.pyi +99 -0
  142. tnfr/mathematics/dynamics.py +408 -0
  143. tnfr/mathematics/dynamics.pyi +90 -0
  144. tnfr/mathematics/epi.py +391 -0
  145. tnfr/mathematics/epi.pyi +65 -0
  146. tnfr/mathematics/generators.py +242 -0
  147. tnfr/mathematics/generators.pyi +29 -0
  148. tnfr/mathematics/metrics.py +119 -0
  149. tnfr/mathematics/metrics.pyi +16 -0
  150. tnfr/mathematics/operators.py +239 -0
  151. tnfr/mathematics/operators.pyi +59 -0
  152. tnfr/mathematics/operators_factory.py +124 -0
  153. tnfr/mathematics/operators_factory.pyi +11 -0
  154. tnfr/mathematics/projection.py +87 -0
  155. tnfr/mathematics/projection.pyi +33 -0
  156. tnfr/mathematics/runtime.py +182 -0
  157. tnfr/mathematics/runtime.pyi +64 -0
  158. tnfr/mathematics/spaces.py +256 -0
  159. tnfr/mathematics/spaces.pyi +83 -0
  160. tnfr/mathematics/transforms.py +305 -0
  161. tnfr/mathematics/transforms.pyi +62 -0
  162. tnfr/metrics/__init__.py +47 -9
  163. tnfr/metrics/__init__.pyi +20 -0
  164. tnfr/metrics/buffer_cache.py +163 -0
  165. tnfr/metrics/buffer_cache.pyi +24 -0
  166. tnfr/metrics/cache_utils.py +214 -0
  167. tnfr/metrics/coherence.py +1510 -330
  168. tnfr/metrics/coherence.pyi +129 -0
  169. tnfr/metrics/common.py +23 -16
  170. tnfr/metrics/common.pyi +35 -0
  171. tnfr/metrics/core.py +251 -36
  172. tnfr/metrics/core.pyi +13 -0
  173. tnfr/metrics/diagnosis.py +709 -110
  174. tnfr/metrics/diagnosis.pyi +86 -0
  175. tnfr/metrics/emergence.py +245 -0
  176. tnfr/metrics/export.py +60 -18
  177. tnfr/metrics/export.pyi +7 -0
  178. tnfr/metrics/glyph_timing.py +233 -43
  179. tnfr/metrics/glyph_timing.pyi +81 -0
  180. tnfr/metrics/learning_metrics.py +280 -0
  181. tnfr/metrics/learning_metrics.pyi +21 -0
  182. tnfr/metrics/phase_coherence.py +351 -0
  183. tnfr/metrics/phase_compatibility.py +349 -0
  184. tnfr/metrics/reporting.py +63 -28
  185. tnfr/metrics/reporting.pyi +25 -0
  186. tnfr/metrics/sense_index.py +1126 -43
  187. tnfr/metrics/sense_index.pyi +9 -0
  188. tnfr/metrics/trig.py +215 -23
  189. tnfr/metrics/trig.pyi +13 -0
  190. tnfr/metrics/trig_cache.py +148 -24
  191. tnfr/metrics/trig_cache.pyi +10 -0
  192. tnfr/multiscale/__init__.py +32 -0
  193. tnfr/multiscale/hierarchical.py +517 -0
  194. tnfr/node.py +646 -140
  195. tnfr/node.pyi +139 -0
  196. tnfr/observers.py +160 -45
  197. tnfr/observers.pyi +31 -0
  198. tnfr/ontosim.py +23 -19
  199. tnfr/ontosim.pyi +28 -0
  200. tnfr/operators/__init__.py +1358 -106
  201. tnfr/operators/__init__.pyi +31 -0
  202. tnfr/operators/algebra.py +277 -0
  203. tnfr/operators/canonical_patterns.py +420 -0
  204. tnfr/operators/cascade.py +267 -0
  205. tnfr/operators/cycle_detection.py +358 -0
  206. tnfr/operators/definitions.py +4108 -0
  207. tnfr/operators/definitions.pyi +78 -0
  208. tnfr/operators/grammar.py +1164 -0
  209. tnfr/operators/grammar.pyi +140 -0
  210. tnfr/operators/hamiltonian.py +710 -0
  211. tnfr/operators/health_analyzer.py +809 -0
  212. tnfr/operators/jitter.py +107 -38
  213. tnfr/operators/jitter.pyi +11 -0
  214. tnfr/operators/lifecycle.py +314 -0
  215. tnfr/operators/metabolism.py +618 -0
  216. tnfr/operators/metrics.py +2138 -0
  217. tnfr/operators/network_analysis/__init__.py +27 -0
  218. tnfr/operators/network_analysis/source_detection.py +186 -0
  219. tnfr/operators/nodal_equation.py +395 -0
  220. tnfr/operators/pattern_detection.py +660 -0
  221. tnfr/operators/patterns.py +669 -0
  222. tnfr/operators/postconditions/__init__.py +38 -0
  223. tnfr/operators/postconditions/mutation.py +236 -0
  224. tnfr/operators/preconditions/__init__.py +1226 -0
  225. tnfr/operators/preconditions/coherence.py +305 -0
  226. tnfr/operators/preconditions/dissonance.py +236 -0
  227. tnfr/operators/preconditions/emission.py +128 -0
  228. tnfr/operators/preconditions/mutation.py +580 -0
  229. tnfr/operators/preconditions/reception.py +125 -0
  230. tnfr/operators/preconditions/resonance.py +364 -0
  231. tnfr/operators/registry.py +74 -0
  232. tnfr/operators/registry.pyi +9 -0
  233. tnfr/operators/remesh.py +1415 -91
  234. tnfr/operators/remesh.pyi +26 -0
  235. tnfr/operators/structural_units.py +268 -0
  236. tnfr/operators/unified_grammar.py +105 -0
  237. tnfr/parallel/__init__.py +54 -0
  238. tnfr/parallel/auto_scaler.py +234 -0
  239. tnfr/parallel/distributed.py +384 -0
  240. tnfr/parallel/engine.py +238 -0
  241. tnfr/parallel/gpu_engine.py +420 -0
  242. tnfr/parallel/monitoring.py +248 -0
  243. tnfr/parallel/partitioner.py +459 -0
  244. tnfr/py.typed +0 -0
  245. tnfr/recipes/__init__.py +22 -0
  246. tnfr/recipes/cookbook.py +743 -0
  247. tnfr/rng.py +75 -151
  248. tnfr/rng.pyi +26 -0
  249. tnfr/schemas/__init__.py +8 -0
  250. tnfr/schemas/grammar.json +94 -0
  251. tnfr/sdk/__init__.py +107 -0
  252. tnfr/sdk/__init__.pyi +19 -0
  253. tnfr/sdk/adaptive_system.py +173 -0
  254. tnfr/sdk/adaptive_system.pyi +21 -0
  255. tnfr/sdk/builders.py +370 -0
  256. tnfr/sdk/builders.pyi +51 -0
  257. tnfr/sdk/fluent.py +1121 -0
  258. tnfr/sdk/fluent.pyi +74 -0
  259. tnfr/sdk/templates.py +342 -0
  260. tnfr/sdk/templates.pyi +41 -0
  261. tnfr/sdk/utils.py +341 -0
  262. tnfr/secure_config.py +46 -0
  263. tnfr/security/__init__.py +70 -0
  264. tnfr/security/database.py +514 -0
  265. tnfr/security/subprocess.py +503 -0
  266. tnfr/security/validation.py +290 -0
  267. tnfr/selector.py +59 -22
  268. tnfr/selector.pyi +19 -0
  269. tnfr/sense.py +92 -67
  270. tnfr/sense.pyi +23 -0
  271. tnfr/services/__init__.py +17 -0
  272. tnfr/services/orchestrator.py +325 -0
  273. tnfr/sparse/__init__.py +39 -0
  274. tnfr/sparse/representations.py +492 -0
  275. tnfr/structural.py +639 -263
  276. tnfr/structural.pyi +83 -0
  277. tnfr/telemetry/__init__.py +35 -0
  278. tnfr/telemetry/cache_metrics.py +226 -0
  279. tnfr/telemetry/cache_metrics.pyi +64 -0
  280. tnfr/telemetry/nu_f.py +422 -0
  281. tnfr/telemetry/nu_f.pyi +108 -0
  282. tnfr/telemetry/verbosity.py +36 -0
  283. tnfr/telemetry/verbosity.pyi +15 -0
  284. tnfr/tokens.py +2 -4
  285. tnfr/tokens.pyi +36 -0
  286. tnfr/tools/__init__.py +20 -0
  287. tnfr/tools/domain_templates.py +478 -0
  288. tnfr/tools/sequence_generator.py +846 -0
  289. tnfr/topology/__init__.py +13 -0
  290. tnfr/topology/asymmetry.py +151 -0
  291. tnfr/trace.py +300 -126
  292. tnfr/trace.pyi +42 -0
  293. tnfr/tutorials/__init__.py +38 -0
  294. tnfr/tutorials/autonomous_evolution.py +285 -0
  295. tnfr/tutorials/interactive.py +1576 -0
  296. tnfr/tutorials/structural_metabolism.py +238 -0
  297. tnfr/types.py +743 -12
  298. tnfr/types.pyi +357 -0
  299. tnfr/units.py +68 -0
  300. tnfr/units.pyi +13 -0
  301. tnfr/utils/__init__.py +282 -0
  302. tnfr/utils/__init__.pyi +215 -0
  303. tnfr/utils/cache.py +4223 -0
  304. tnfr/utils/cache.pyi +470 -0
  305. tnfr/{callback_utils.py → utils/callbacks.py} +26 -39
  306. tnfr/utils/callbacks.pyi +49 -0
  307. tnfr/utils/chunks.py +108 -0
  308. tnfr/utils/chunks.pyi +22 -0
  309. tnfr/utils/data.py +428 -0
  310. tnfr/utils/data.pyi +74 -0
  311. tnfr/utils/graph.py +85 -0
  312. tnfr/utils/graph.pyi +10 -0
  313. tnfr/utils/init.py +821 -0
  314. tnfr/utils/init.pyi +80 -0
  315. tnfr/utils/io.py +559 -0
  316. tnfr/utils/io.pyi +66 -0
  317. tnfr/{helpers → utils}/numeric.py +51 -24
  318. tnfr/utils/numeric.pyi +21 -0
  319. tnfr/validation/__init__.py +257 -0
  320. tnfr/validation/__init__.pyi +85 -0
  321. tnfr/validation/compatibility.py +460 -0
  322. tnfr/validation/compatibility.pyi +6 -0
  323. tnfr/validation/config.py +73 -0
  324. tnfr/validation/graph.py +139 -0
  325. tnfr/validation/graph.pyi +18 -0
  326. tnfr/validation/input_validation.py +755 -0
  327. tnfr/validation/invariants.py +712 -0
  328. tnfr/validation/rules.py +253 -0
  329. tnfr/validation/rules.pyi +44 -0
  330. tnfr/validation/runtime.py +279 -0
  331. tnfr/validation/runtime.pyi +28 -0
  332. tnfr/validation/sequence_validator.py +162 -0
  333. tnfr/validation/soft_filters.py +170 -0
  334. tnfr/validation/soft_filters.pyi +32 -0
  335. tnfr/validation/spectral.py +164 -0
  336. tnfr/validation/spectral.pyi +42 -0
  337. tnfr/validation/validator.py +1266 -0
  338. tnfr/validation/window.py +39 -0
  339. tnfr/validation/window.pyi +1 -0
  340. tnfr/visualization/__init__.py +98 -0
  341. tnfr/visualization/cascade_viz.py +256 -0
  342. tnfr/visualization/hierarchy.py +284 -0
  343. tnfr/visualization/sequence_plotter.py +784 -0
  344. tnfr/viz/__init__.py +60 -0
  345. tnfr/viz/matplotlib.py +278 -0
  346. tnfr/viz/matplotlib.pyi +35 -0
  347. tnfr-8.5.0.dist-info/METADATA +573 -0
  348. tnfr-8.5.0.dist-info/RECORD +353 -0
  349. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/entry_points.txt +1 -0
  350. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/licenses/LICENSE.md +1 -1
  351. tnfr/collections_utils.py +0 -300
  352. tnfr/config.py +0 -32
  353. tnfr/grammar.py +0 -344
  354. tnfr/graph_utils.py +0 -84
  355. tnfr/helpers/__init__.py +0 -71
  356. tnfr/import_utils.py +0 -228
  357. tnfr/json_utils.py +0 -162
  358. tnfr/logging_utils.py +0 -116
  359. tnfr/presets.py +0 -60
  360. tnfr/validators.py +0 -84
  361. tnfr/value_utils.py +0 -59
  362. tnfr-4.5.2.dist-info/METADATA +0 -379
  363. tnfr-4.5.2.dist-info/RECORD +0 -67
  364. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
  365. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
tnfr/node.pyi ADDED
@@ -0,0 +1,139 @@
1
+ from __future__ import annotations
2
+
3
+ import numpy as np
4
+ from .mathematics import (
5
+ CoherenceOperator,
6
+ FrequencyOperator,
7
+ HilbertSpace,
8
+ NFRValidator,
9
+ StateProjector,
10
+ )
11
+ from .types import (
12
+ CouplingWeight,
13
+ DeltaNFR,
14
+ EPIValue,
15
+ NodeId,
16
+ Phase,
17
+ SecondDerivativeEPI,
18
+ SenseIndex,
19
+ StructuralFrequency,
20
+ TNFRGraph,
21
+ )
22
+ from collections.abc import Hashable
23
+ from dataclasses import dataclass
24
+ from typing import (
25
+ Any,
26
+ Callable,
27
+ Iterable,
28
+ MutableMapping,
29
+ Protocol,
30
+ Sequence,
31
+ SupportsFloat,
32
+ TypeVar,
33
+ )
34
+
35
+ __all__ = ["NodeNX", "NodeProtocol", "add_edge"]
36
+
37
+ T = TypeVar("T")
38
+
39
+ @dataclass(frozen=True)
40
+ class AttrSpec:
41
+ aliases: tuple[str, ...]
42
+ default: Any = ...
43
+ getter: Callable[[MutableMapping[str, Any], tuple[str, ...], Any], Any] = ...
44
+ setter: Callable[..., None] = ...
45
+ to_python: Callable[[Any], Any] = ...
46
+ to_storage: Callable[[Any], Any] = ...
47
+ use_graph_setter: bool = ...
48
+ def build_property(self) -> property: ...
49
+
50
+ def add_edge(
51
+ graph: TNFRGraph,
52
+ n1: NodeId,
53
+ n2: NodeId,
54
+ weight: CouplingWeight | SupportsFloat | str,
55
+ overwrite: bool = False,
56
+ ) -> None: ...
57
+
58
+ class NodeProtocol(Protocol):
59
+ EPI: EPIValue
60
+ vf: StructuralFrequency
61
+ theta: Phase
62
+ Si: SenseIndex
63
+ epi_kind: str
64
+ dnfr: DeltaNFR
65
+ d2EPI: SecondDerivativeEPI
66
+ graph: MutableMapping[str, Any]
67
+ def neighbors(self) -> Iterable[NodeProtocol | Hashable]: ...
68
+ def has_edge(self, other: NodeProtocol) -> bool: ...
69
+ def add_edge(
70
+ self, other: NodeProtocol, weight: CouplingWeight, *, overwrite: bool = False
71
+ ) -> None: ...
72
+ def offset(self) -> int: ...
73
+ def all_nodes(self) -> Iterable[NodeProtocol]: ...
74
+
75
+ class NodeNX(NodeProtocol):
76
+ EPI: EPIValue
77
+ vf: StructuralFrequency
78
+ theta: Phase
79
+ Si: SenseIndex
80
+ epi_kind: str
81
+ dnfr: DeltaNFR
82
+ d2EPI: SecondDerivativeEPI
83
+ G: TNFRGraph
84
+ n: NodeId
85
+ graph: MutableMapping[str, Any]
86
+ state_projector: StateProjector
87
+ enable_math_validation: bool
88
+ hilbert_space: HilbertSpace
89
+ coherence_operator: CoherenceOperator | None
90
+ frequency_operator: FrequencyOperator | None
91
+ coherence_threshold: float | None
92
+ validator: NFRValidator | None
93
+ rng: np.random.Generator | None
94
+ def __init__(
95
+ self,
96
+ G: TNFRGraph,
97
+ n: NodeId,
98
+ *,
99
+ state_projector: StateProjector | None = None,
100
+ enable_math_validation: bool | None = None,
101
+ hilbert_space: HilbertSpace | None = None,
102
+ coherence_operator: CoherenceOperator | None = None,
103
+ coherence_dim: int | None = None,
104
+ coherence_spectrum: Sequence[float] | np.ndarray | None = None,
105
+ coherence_c_min: float | None = None,
106
+ frequency_operator: FrequencyOperator | None = None,
107
+ frequency_matrix: Sequence[Sequence[complex]] | np.ndarray | None = None,
108
+ coherence_threshold: float | None = None,
109
+ validator: NFRValidator | None = None,
110
+ rng: np.random.Generator | None = None,
111
+ ) -> None: ...
112
+ @classmethod
113
+ def from_graph(cls, G: TNFRGraph, n: NodeId) -> NodeNX: ...
114
+ def neighbors(self) -> Iterable[NodeId]: ...
115
+ def has_edge(self, other: NodeProtocol) -> bool: ...
116
+ def add_edge(
117
+ self, other: NodeProtocol, weight: CouplingWeight, *, overwrite: bool = False
118
+ ) -> None: ...
119
+ def offset(self) -> int: ...
120
+ def all_nodes(self) -> Iterable[NodeProtocol]: ...
121
+ def run_sequence_with_validation(
122
+ self,
123
+ ops: Iterable[Callable[[TNFRGraph, NodeId], None]],
124
+ *,
125
+ projector: StateProjector | None = None,
126
+ hilbert_space: HilbertSpace | None = None,
127
+ coherence_operator: CoherenceOperator | None = None,
128
+ coherence_dim: int | None = None,
129
+ coherence_spectrum: Sequence[float] | np.ndarray | None = None,
130
+ coherence_c_min: float | None = None,
131
+ coherence_threshold: float | None = None,
132
+ frequency_operator: FrequencyOperator | None = None,
133
+ frequency_matrix: Sequence[Sequence[complex]] | np.ndarray | None = None,
134
+ validator: NFRValidator | None = None,
135
+ enforce_frequency_positivity: bool | None = None,
136
+ enable_validation: bool | None = None,
137
+ rng: np.random.Generator | None = None,
138
+ log_metrics: bool = False,
139
+ ) -> dict[str, Any]: ...
tnfr/observers.py CHANGED
@@ -1,28 +1,32 @@
1
1
  """Observer management."""
2
2
 
3
3
  from __future__ import annotations
4
- from functools import partial
4
+
5
5
  import statistics
6
+ from collections.abc import Mapping
7
+ from functools import partial
6
8
  from statistics import StatisticsError, pvariance
7
9
 
8
- from .constants import get_aliases
9
- from .alias import get_attr
10
- from .helpers.numeric import angle_diff
11
- from .callback_utils import CallbackEvent, callback_manager
10
+ from .alias import get_theta_attr
11
+ from .utils import CallbackEvent, callback_manager
12
+ from .config.constants import GLYPH_GROUPS
13
+ from .gamma import kuramoto_R_psi
12
14
  from .glyph_history import (
13
- ensure_history,
14
- count_glyphs,
15
15
  append_metric,
16
+ count_glyphs,
17
+ ensure_history,
16
18
  )
17
- from .collections_utils import normalize_counter, mix_groups
18
- from .constants_glyphs import GLYPH_GROUPS
19
- from .gamma import kuramoto_R_psi
20
- from .logging_utils import get_logger
21
- from .import_utils import get_numpy
19
+ from .utils import angle_diff
22
20
  from .metrics.common import compute_coherence
23
- from .validators import validate_window
24
-
25
- ALIAS_THETA = get_aliases("THETA")
21
+ from .types import Glyph, GlyphLoadDistribution, TNFRGraph
22
+ from .utils import (
23
+ get_logger,
24
+ get_numpy,
25
+ mix_groups,
26
+ normalize_counter,
27
+ )
28
+ from .validation import validate_window
29
+ from .telemetry import ensure_nu_f_telemetry, record_nu_f_window
26
30
 
27
31
  __all__ = (
28
32
  "attach_standard_observer",
@@ -35,18 +39,16 @@ __all__ = (
35
39
  "DEFAULT_WBAR_SPAN",
36
40
  )
37
41
 
38
-
39
42
  logger = get_logger(__name__)
40
43
 
41
44
  DEFAULT_GLYPH_LOAD_SPAN = 50
42
45
  DEFAULT_WBAR_SPAN = 25
43
46
 
44
47
 
45
-
46
48
  # -------------------------
47
- # Observador estándar Γ(R)
49
+ # Standard Γ(R) observer
48
50
  # -------------------------
49
- def _std_log(kind: str, G, ctx: dict):
51
+ def _std_log(kind: str, G: TNFRGraph, ctx: Mapping[str, object]) -> None:
50
52
  """Store compact events in ``history['events']``."""
51
53
  h = ensure_history(G)
52
54
  append_metric(h, "events", (kind, dict(ctx)))
@@ -56,25 +58,123 @@ _STD_CALLBACKS = {
56
58
  CallbackEvent.BEFORE_STEP.value: partial(_std_log, "before"),
57
59
  CallbackEvent.AFTER_STEP.value: partial(_std_log, "after"),
58
60
  CallbackEvent.ON_REMESH.value: partial(_std_log, "remesh"),
61
+ CallbackEvent.CACHE_METRICS.value: partial(_std_log, "cache"),
59
62
  }
60
63
 
64
+ _REORG_STATE_KEY = "_std_observer_reorg"
65
+
66
+
67
+ def _resolve_reorg_state(G: TNFRGraph) -> dict[str, object]:
68
+ state = G.graph.get(_REORG_STATE_KEY)
69
+ if not isinstance(state, dict):
70
+ state = {}
71
+ G.graph[_REORG_STATE_KEY] = state
72
+ return state
73
+
74
+
75
+ def _before_step_reorg(G: TNFRGraph, ctx: Mapping[str, object] | None) -> None:
76
+ """Capture structural time metadata before the step starts."""
77
+
78
+ ensure_nu_f_telemetry(G, confidence_level=None)
79
+ state = _resolve_reorg_state(G)
80
+ step_idx = ctx.get("step") if ctx else None
81
+ try:
82
+ state["step"] = int(step_idx) if step_idx is not None else None
83
+ except (TypeError, ValueError):
84
+ state["step"] = None
85
+ start_t = float(G.graph.get("_t", 0.0))
86
+ state["start_t"] = start_t
87
+ dt_raw = ctx.get("dt") if ctx else None
88
+ try:
89
+ state["dt"] = float(dt_raw) if dt_raw is not None else None
90
+ except (TypeError, ValueError):
91
+ state["dt"] = None
92
+
61
93
 
62
- def attach_standard_observer(G):
94
+ def _after_step_reorg(G: TNFRGraph, ctx: Mapping[str, object] | None) -> None:
95
+ """Record the reorganisation window for νf telemetry."""
96
+
97
+ state = _resolve_reorg_state(G)
98
+ pending_step = state.get("step")
99
+ ctx_step = ctx.get("step") if ctx else None
100
+ if pending_step is not None and ctx_step is not None and pending_step != ctx_step:
101
+ # Ignore mismatched callbacks to avoid double counting.
102
+ return
103
+
104
+ try:
105
+ start_t = float(state.get("start_t", float(G.graph.get("_t", 0.0))))
106
+ except (TypeError, ValueError):
107
+ start_t = float(G.graph.get("_t", 0.0))
108
+ end_t = float(G.graph.get("_t", start_t))
109
+ dt_raw = state.get("dt")
110
+ try:
111
+ duration = float(dt_raw) if dt_raw is not None else end_t - start_t
112
+ except (TypeError, ValueError):
113
+ duration = end_t - start_t
114
+ if duration <= 0.0:
115
+ duration = end_t - start_t
116
+ if duration <= 0.0:
117
+ return
118
+
119
+ stable_frac = ctx.get("stable_frac") if ctx else None
120
+ if stable_frac is None:
121
+ hist = ensure_history(G)
122
+ series = hist.get("stable_frac", [])
123
+ stable_frac = series[-1] if series else None
124
+ try:
125
+ stable_frac_f = float(stable_frac) if stable_frac is not None else None
126
+ except (TypeError, ValueError):
127
+ stable_frac_f = None
128
+ total_nodes = G.number_of_nodes()
129
+ if stable_frac_f is None:
130
+ reorganisations = total_nodes
131
+ else:
132
+ frac = min(max(stable_frac_f, 0.0), 1.0)
133
+ stable_nodes = int(round(frac * total_nodes))
134
+ reorganisations = max(total_nodes - stable_nodes, 0)
135
+
136
+ record_nu_f_window(
137
+ G,
138
+ reorganisations,
139
+ duration,
140
+ start=start_t,
141
+ end=end_t,
142
+ )
143
+ state["last_duration"] = duration
144
+ state["last_reorganisations"] = reorganisations
145
+ state["last_end_t"] = end_t
146
+ state["step"] = None
147
+
148
+
149
+ def attach_standard_observer(G: TNFRGraph) -> TNFRGraph:
63
150
  """Register standard callbacks: before_step, after_step, on_remesh."""
64
151
  if G.graph.get("_STD_OBSERVER"):
65
152
  return G
66
153
  for event, fn in _STD_CALLBACKS.items():
67
154
  callback_manager.register_callback(G, event, fn)
155
+ callback_manager.register_callback(
156
+ G,
157
+ CallbackEvent.BEFORE_STEP.value,
158
+ _before_step_reorg,
159
+ name="std_reorg_before",
160
+ )
161
+ callback_manager.register_callback(
162
+ G,
163
+ CallbackEvent.AFTER_STEP.value,
164
+ _after_step_reorg,
165
+ name="std_reorg_after",
166
+ )
167
+ ensure_nu_f_telemetry(G, confidence_level=None)
68
168
  G.graph["_STD_OBSERVER"] = "attached"
69
169
  return G
70
170
 
71
171
 
72
- def _ensure_nodes(G) -> bool:
172
+ def _ensure_nodes(G: TNFRGraph) -> bool:
73
173
  """Return ``True`` when the graph has nodes."""
74
174
  return bool(G.number_of_nodes())
75
175
 
76
176
 
77
- def kuramoto_metrics(G) -> tuple[float, float]:
177
+ def kuramoto_metrics(G: TNFRGraph) -> tuple[float, float]:
78
178
  """Return Kuramoto order ``R`` and mean phase ``ψ``.
79
179
 
80
180
  Delegates to :func:`kuramoto_R_psi` and performs the computation exactly
@@ -83,19 +183,23 @@ def kuramoto_metrics(G) -> tuple[float, float]:
83
183
  return kuramoto_R_psi(G)
84
184
 
85
185
 
86
- def phase_sync(G, R: float | None = None, psi: float | None = None) -> float:
186
+ def phase_sync(
187
+ G: TNFRGraph,
188
+ R: float | None = None,
189
+ psi: float | None = None,
190
+ ) -> float:
191
+ """Return a [0, 1] synchrony index derived from phase dispersion."""
192
+
87
193
  if not _ensure_nodes(G):
88
194
  return 1.0
89
- if R is None or psi is None:
90
- R_calc, psi_calc = kuramoto_metrics(G)
91
- if R is None:
92
- R = R_calc
93
- if psi is None:
94
- psi = psi_calc
95
- diffs = (
96
- angle_diff(get_attr(data, ALIAS_THETA, 0.0), psi)
97
- for _, data in G.nodes(data=True)
98
- )
195
+ if psi is None:
196
+ _, psi = kuramoto_metrics(G)
197
+
198
+ def _theta(nd: Mapping[str, object]) -> float:
199
+ value = get_theta_attr(nd, 0.0)
200
+ return float(value) if value is not None else 0.0
201
+
202
+ diffs = (angle_diff(_theta(data), psi) for _, data in G.nodes(data=True))
99
203
  # Try NumPy for a vectorised population variance
100
204
  np = get_numpy()
101
205
  if np is not None:
@@ -110,7 +214,7 @@ def phase_sync(G, R: float | None = None, psi: float | None = None) -> float:
110
214
 
111
215
 
112
216
  def kuramoto_order(
113
- G, R: float | None = None, psi: float | None = None
217
+ G: TNFRGraph, R: float | None = None, psi: float | None = None
114
218
  ) -> float:
115
219
  """R in [0,1], 1 means perfectly aligned phases."""
116
220
  if not _ensure_nodes(G):
@@ -120,29 +224,40 @@ def kuramoto_order(
120
224
  return float(R)
121
225
 
122
226
 
123
- def glyph_load(G, window: int | None = None) -> dict:
124
- """Return distribution of glyphs applied in the network.
227
+ def glyph_load(G: TNFRGraph, window: int | None = None) -> GlyphLoadDistribution:
228
+ """Return distribution of structural operators applied in the network.
229
+
230
+ Analyzes which structural operator symbols (glyphs) have been applied to
231
+ nodes in the network over a given time window.
125
232
 
126
233
  - ``window``: if provided, count only the last ``window`` events per node;
127
234
  otherwise use :data:`DEFAULT_GLYPH_LOAD_SPAN`.
128
- Returns a dict with proportions per glyph and useful aggregates.
235
+
236
+ Returns a dict with proportions per structural operator symbol and useful aggregates.
129
237
  """
130
238
  if window == 0:
131
- return {"_count": 0}
239
+ return {"_count": 0.0}
132
240
  if window is None:
133
241
  window_int = DEFAULT_GLYPH_LOAD_SPAN
134
242
  else:
135
243
  window_int = validate_window(window, positive=True)
136
244
  total = count_glyphs(G, window=window_int, last_only=(window_int == 1))
137
- dist, count = normalize_counter(total)
245
+ dist_raw, count = normalize_counter(total)
138
246
  if count == 0:
139
- return {"_count": 0}
140
- dist = mix_groups(dist, GLYPH_GROUPS)
141
- dist["_count"] = count
142
- return dist
247
+ return {"_count": 0.0}
248
+ dist = mix_groups(dist_raw, GLYPH_GROUPS)
249
+ glyph_dist: GlyphLoadDistribution = {}
250
+ for key, value in dist.items():
251
+ try:
252
+ glyph_key: Glyph | str = Glyph(key)
253
+ except ValueError:
254
+ glyph_key = key
255
+ glyph_dist[glyph_key] = value
256
+ glyph_dist["_count"] = float(count)
257
+ return glyph_dist
143
258
 
144
259
 
145
- def wbar(G, window: int | None = None) -> float:
260
+ def wbar(G: TNFRGraph, window: int | None = None) -> float:
146
261
  """Return W̄ = mean of ``C(t)`` over a recent window.
147
262
 
148
263
  Uses :func:`ensure_history` to obtain ``G.graph['history']`` and falls back
@@ -151,7 +266,7 @@ def wbar(G, window: int | None = None) -> float:
151
266
  hist = ensure_history(G)
152
267
  cs = list(hist.get("C_steps", []))
153
268
  if not cs:
154
- # fallback: coherencia instantánea
269
+ # fallback: instantaneous coherence
155
270
  return compute_coherence(G)
156
271
  w_param = DEFAULT_WBAR_SPAN if window is None else window
157
272
  w = validate_window(w_param, positive=True)
tnfr/observers.pyi ADDED
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Mapping
4
+ from typing import Final
5
+
6
+ from .types import GlyphLoadDistribution, TNFRGraph
7
+
8
+ __all__: tuple[str, ...]
9
+
10
+ DEFAULT_GLYPH_LOAD_SPAN: Final[int]
11
+ DEFAULT_WBAR_SPAN: Final[int]
12
+
13
+ def _std_log(kind: str, G: TNFRGraph, ctx: Mapping[str, object]) -> None: ...
14
+ def attach_standard_observer(G: TNFRGraph) -> TNFRGraph: ...
15
+ def _ensure_nodes(G: TNFRGraph) -> bool: ...
16
+ def kuramoto_metrics(G: TNFRGraph) -> tuple[float, float]: ...
17
+ def phase_sync(
18
+ G: TNFRGraph,
19
+ R: float | None = ...,
20
+ psi: float | None = ...,
21
+ ) -> float: ...
22
+ def kuramoto_order(
23
+ G: TNFRGraph,
24
+ R: float | None = ...,
25
+ psi: float | None = ...,
26
+ ) -> float: ...
27
+ def glyph_load(
28
+ G: TNFRGraph,
29
+ window: int | None = ...,
30
+ ) -> GlyphLoadDistribution: ...
31
+ def wbar(G: TNFRGraph, window: int | None = ...) -> float: ...
tnfr/ontosim.py CHANGED
@@ -1,25 +1,27 @@
1
1
  """Orchestrate the canonical simulation."""
2
2
 
3
3
  from __future__ import annotations
4
+
4
5
  from collections import deque
5
6
  from typing import TYPE_CHECKING
6
7
 
7
- from .callback_utils import CallbackEvent
8
- from .constants import METRIC_DEFAULTS, inject_defaults, get_param
9
- from .dynamics import step as _step, run as _run
8
+ from .utils import CallbackEvent
9
+ from .constants import METRIC_DEFAULTS, get_param, inject_defaults
10
10
  from .dynamics import default_compute_delta_nfr
11
- from .initialization import init_node_attrs
11
+ from .dynamics import run as _run
12
+ from .dynamics import step as _step
12
13
  from .glyph_history import append_metric
13
- from .import_utils import cached_import
14
+ from .initialization import init_node_attrs
15
+ from .utils import cached_import
14
16
 
15
17
  if TYPE_CHECKING: # pragma: no cover
16
- import networkx as nx # type: ignore[import-untyped]
18
+ import networkx as nx
17
19
 
18
- # API de alto nivel
19
- __all__ = ("preparar_red", "step", "run")
20
+ # High-level API exports
21
+ __all__ = ("prepare_network", "step", "run")
20
22
 
21
23
 
22
- def preparar_red(
24
+ def prepare_network(
23
25
  G: "nx.Graph",
24
26
  *,
25
27
  init_attrs: bool = True,
@@ -43,11 +45,9 @@ def preparar_red(
43
45
  from .constants import merge_overrides
44
46
 
45
47
  merge_overrides(G, **overrides)
46
- # Inicializaciones blandas
48
+ # Initialize history buffers
47
49
  ph_len = int(
48
- G.graph.get(
49
- "PHASE_HISTORY_MAXLEN", METRIC_DEFAULTS["PHASE_HISTORY_MAXLEN"]
50
- )
50
+ G.graph.get("PHASE_HISTORY_MAXLEN", METRIC_DEFAULTS["PHASE_HISTORY_MAXLEN"])
51
51
  )
52
52
  hist_keys = [
53
53
  "C_steps",
@@ -59,7 +59,7 @@ def preparar_red(
59
59
  "sense_sigma_mag",
60
60
  "sense_sigma_angle",
61
61
  "iota",
62
- "glyph_load_estab",
62
+ "glyph_load_stabilizers",
63
63
  "glyph_load_disr",
64
64
  "Si_mean",
65
65
  "Si_hi_frac",
@@ -77,11 +77,11 @@ def preparar_red(
77
77
  }
78
78
  )
79
79
  G.graph.setdefault("history", history)
80
- # Memoria global de REMESH
80
+ # Global REMESH memory
81
81
  tau = int(get_param(G, "REMESH_TAU_GLOBAL"))
82
82
  maxlen = max(2 * tau + 5, 64)
83
83
  G.graph.setdefault("_epi_hist", deque(maxlen=maxlen))
84
- # Auto-attach del observador estándar si se pide
84
+ # Auto-attach the standard observer when requested
85
85
  if G.graph.get("ATTACH_STD_OBSERVER", False):
86
86
  attach_standard_observer = cached_import(
87
87
  "tnfr.observers",
@@ -95,7 +95,7 @@ def preparar_red(
95
95
  "_callback_errors",
96
96
  {"event": "attach_std_observer", "error": "ImportError"},
97
97
  )
98
- # Hook explícito para ΔNFR (se puede sustituir luego con
98
+ # Explicit hook for ΔNFR (can later be replaced with
99
99
  # dynamics.set_delta_nfr_hook)
100
100
  G.graph.setdefault("compute_delta_nfr", default_compute_delta_nfr)
101
101
  G.graph.setdefault("_dnfr_hook_name", "default_compute_delta_nfr")
@@ -110,8 +110,8 @@ def preparar_red(
110
110
  )
111
111
  G.graph.setdefault(
112
112
  "_CALLBACKS_DOC",
113
- "Interfaz Γ(R): registrar pares (name, func) con firma (G, ctx) "
114
- "en callbacks['before_step'|'after_step'|'on_remesh']",
113
+ "Γ(R) interface: register (name, func) pairs with signature (G, ctx) "
114
+ "in callbacks['before_step'|'after_step'|'on_remesh']",
115
115
  )
116
116
 
117
117
  if init_attrs:
@@ -126,6 +126,8 @@ def step(
126
126
  use_Si: bool = True,
127
127
  apply_glyphs: bool = True,
128
128
  ) -> None:
129
+ """Advance the ontosim runtime by a single step."""
130
+
129
131
  _step(G, dt=dt, use_Si=use_Si, apply_glyphs=apply_glyphs)
130
132
 
131
133
 
@@ -137,4 +139,6 @@ def run(
137
139
  use_Si: bool = True,
138
140
  apply_glyphs: bool = True,
139
141
  ) -> None:
142
+ """Advance the ontosim runtime ``steps`` times with optional overrides."""
143
+
140
144
  _run(G, steps=steps, dt=dt, use_Si=use_Si, apply_glyphs=apply_glyphs)
tnfr/ontosim.pyi ADDED
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+
3
+ from .types import TNFRConfigValue, TNFRGraph
4
+
5
+ __all__: tuple[str, ...]
6
+
7
+ def prepare_network(
8
+ G: TNFRGraph,
9
+ *,
10
+ init_attrs: bool = True,
11
+ override_defaults: bool = False,
12
+ **overrides: TNFRConfigValue,
13
+ ) -> TNFRGraph: ...
14
+ def step(
15
+ G: TNFRGraph,
16
+ *,
17
+ dt: float | None = None,
18
+ use_Si: bool = True,
19
+ apply_glyphs: bool = True,
20
+ ) -> None: ...
21
+ def run(
22
+ G: TNFRGraph,
23
+ steps: int,
24
+ *,
25
+ dt: float | None = None,
26
+ use_Si: bool = True,
27
+ apply_glyphs: bool = True,
28
+ ) -> None: ...