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/execution.py CHANGED
@@ -4,28 +4,24 @@ from __future__ import annotations
4
4
 
5
5
  from collections import deque
6
6
  from collections.abc import Callable, Iterable, Sequence
7
- from typing import Any, Optional
7
+ from typing import Any, Optional, cast
8
8
 
9
- import networkx as nx # networkx is used at runtime
10
-
11
- from .collections_utils import (
12
- MAX_MATERIALIZE_DEFAULT,
13
- ensure_collection,
14
- is_non_string_sequence,
15
- )
9
+ from ._compat import TypeAlias
16
10
  from .constants import get_param
17
11
  from .dynamics import step
18
12
  from .flatten import _flatten
19
13
  from .glyph_history import ensure_history
20
- from .grammar import apply_glyph_with_grammar
21
- from .tokens import OpTag, TARGET, THOL, WAIT, Token
22
- from .types import Glyph
23
-
24
- Node = Any
25
- AdvanceFn = Callable[[Any], None]
14
+ from .tokens import TARGET, THOL, WAIT, OpTag, Token
15
+ from .types import Glyph, NodeId, TNFRGraph
16
+ from .utils import MAX_MATERIALIZE_DEFAULT, ensure_collection, is_non_string_sequence
17
+ from .validation import apply_glyph_with_grammar
18
+
19
+ AdvanceFn = Callable[[TNFRGraph], None]
20
+ TraceEntry = dict[str, Any]
21
+ ProgramTrace: TypeAlias = deque[TraceEntry]
26
22
  HandlerFn = Callable[
27
- [nx.Graph, Any, Optional[list[Node]], deque, AdvanceFn],
28
- Optional[list[Node]],
23
+ [TNFRGraph, Any, Optional[Sequence[NodeId]], ProgramTrace, AdvanceFn],
24
+ Optional[Sequence[NodeId]],
29
25
  ]
30
26
 
31
27
  __all__ = [
@@ -44,25 +40,25 @@ __all__ = [
44
40
  "wait",
45
41
  ]
46
42
 
47
-
48
- CANONICAL_PRESET_NAME = "ejemplo_canonico"
43
+ CANONICAL_PRESET_NAME = "canonical_example"
49
44
  CANONICAL_PROGRAM_TOKENS: tuple[Token, ...] = (
50
- Glyph.SHA,
51
- Glyph.AL,
52
- Glyph.RA,
53
- Glyph.ZHIR,
54
- Glyph.NUL,
55
- Glyph.THOL,
45
+ Glyph.SHA, # silence - initial stabilization
46
+ Glyph.AL, # emission - initiate pattern
47
+ Glyph.RA, # reception - capture information
48
+ Glyph.OZ, # dissonance - required before mutation (grammar rule)
49
+ Glyph.ZHIR, # mutation - phase change
50
+ Glyph.NUL, # contraction - compress structure
51
+ Glyph.THOL, # self_organization - recursive reorganization
56
52
  )
57
53
 
58
54
 
59
- def _window(G) -> int:
55
+ def _window(G: TNFRGraph) -> int:
60
56
  return int(get_param(G, "GLYPH_HYSTERESIS_WINDOW"))
61
57
 
62
58
 
63
59
  def _apply_glyph_to_targets(
64
- G, g: Glyph | str, nodes: Optional[Iterable[Node]] = None
65
- ):
60
+ G: TNFRGraph, g: Glyph | str, nodes: Optional[Iterable[NodeId]] = None
61
+ ) -> None:
66
62
  """Apply ``g`` to ``nodes`` (or all nodes) respecting the grammar."""
67
63
 
68
64
  nodes_iter = G.nodes() if nodes is None else nodes
@@ -70,22 +66,24 @@ def _apply_glyph_to_targets(
70
66
  apply_glyph_with_grammar(G, nodes_iter, g, w)
71
67
 
72
68
 
73
- def _advance(G, step_fn: AdvanceFn):
69
+ def _advance(G: TNFRGraph, step_fn: AdvanceFn) -> None:
74
70
  step_fn(G)
75
71
 
76
72
 
77
- def _record_trace(trace: deque, G, op: OpTag, **data) -> None:
73
+ def _record_trace(trace: ProgramTrace, G: TNFRGraph, op: OpTag, **data: Any) -> None:
74
+ """Append an operation snapshot to ``trace`` using graph time metadata."""
75
+
78
76
  trace.append({"t": float(G.graph.get("_t", 0.0)), "op": op.name, **data})
79
77
 
80
78
 
81
79
  def _advance_and_record(
82
- G,
83
- trace: deque,
80
+ G: TNFRGraph,
81
+ trace: ProgramTrace,
84
82
  label: OpTag,
85
83
  step_fn: AdvanceFn,
86
84
  *,
87
85
  times: int = 1,
88
- **data,
86
+ **data: Any,
89
87
  ) -> None:
90
88
  for _ in range(times):
91
89
  _advance(G, step_fn)
@@ -93,40 +91,55 @@ def _advance_and_record(
93
91
 
94
92
 
95
93
  def _handle_target(
96
- G, payload: TARGET, _curr_target, trace: deque, _step_fn: AdvanceFn
97
- ):
94
+ G: TNFRGraph,
95
+ payload: TARGET,
96
+ _curr_target: Optional[Sequence[NodeId]],
97
+ trace: ProgramTrace,
98
+ _step_fn: AdvanceFn,
99
+ ) -> Sequence[NodeId]:
98
100
  """Handle a ``TARGET`` token and return the active node set."""
99
101
 
100
102
  nodes_src = G.nodes() if payload.nodes is None else payload.nodes
101
103
  nodes = ensure_collection(nodes_src, max_materialize=None)
102
- curr_target = nodes if is_non_string_sequence(nodes) else tuple(nodes)
104
+ if is_non_string_sequence(nodes):
105
+ curr_target = cast(Sequence[NodeId], nodes)
106
+ else:
107
+ curr_target = tuple(nodes)
103
108
  _record_trace(trace, G, OpTag.TARGET, n=len(curr_target))
104
109
  return curr_target
105
110
 
106
111
 
107
112
  def _handle_wait(
108
- G, steps: int, curr_target, trace: deque, step_fn: AdvanceFn
109
- ):
113
+ G: TNFRGraph,
114
+ steps: int,
115
+ curr_target: Optional[Sequence[NodeId]],
116
+ trace: ProgramTrace,
117
+ step_fn: AdvanceFn,
118
+ ) -> Optional[Sequence[NodeId]]:
110
119
  _advance_and_record(G, trace, OpTag.WAIT, step_fn, times=steps, k=steps)
111
120
  return curr_target
112
121
 
113
122
 
114
123
  def _handle_glyph(
115
- G,
116
- g: str,
117
- curr_target,
118
- trace: deque,
124
+ G: TNFRGraph,
125
+ g: Glyph | str,
126
+ curr_target: Optional[Sequence[NodeId]],
127
+ trace: ProgramTrace,
119
128
  step_fn: AdvanceFn,
120
129
  label: OpTag = OpTag.GLYPH,
121
- ):
130
+ ) -> Optional[Sequence[NodeId]]:
122
131
  _apply_glyph_to_targets(G, g, curr_target)
123
132
  _advance_and_record(G, trace, label, step_fn, g=g)
124
133
  return curr_target
125
134
 
126
135
 
127
136
  def _handle_thol(
128
- G, g, curr_target, trace: deque, step_fn: AdvanceFn
129
- ):
137
+ G: TNFRGraph,
138
+ g: Glyph | str | None,
139
+ curr_target: Optional[Sequence[NodeId]],
140
+ trace: ProgramTrace,
141
+ step_fn: AdvanceFn,
142
+ ) -> Optional[Sequence[NodeId]]:
130
143
  return _handle_glyph(
131
144
  G, g or Glyph.THOL.value, curr_target, trace, step_fn, label=OpTag.THOL
132
145
  )
@@ -141,20 +154,23 @@ HANDLERS: dict[OpTag, HandlerFn] = {
141
154
 
142
155
 
143
156
  def play(
144
- G, sequence: Sequence[Token], step_fn: Optional[AdvanceFn] = None
157
+ G: TNFRGraph, sequence: Sequence[Token], step_fn: Optional[AdvanceFn] = None
145
158
  ) -> None:
146
159
  """Execute a canonical sequence on graph ``G``."""
147
160
 
148
161
  step_fn = step_fn or step
149
162
 
150
- curr_target: Optional[list[Node]] = None
163
+ curr_target: Optional[Sequence[NodeId]] = None
151
164
 
152
165
  history = ensure_history(G)
153
166
  maxlen = int(get_param(G, "PROGRAM_TRACE_MAXLEN"))
154
- trace = history.get("program_trace")
155
- if not isinstance(trace, deque) or trace.maxlen != maxlen:
156
- trace = deque(trace or [], maxlen=maxlen)
167
+ trace_obj = history.get("program_trace")
168
+ trace: ProgramTrace
169
+ if not isinstance(trace_obj, deque) or trace_obj.maxlen != maxlen:
170
+ trace = cast(ProgramTrace, deque(trace_obj or [], maxlen=maxlen))
157
171
  history["program_trace"] = trace
172
+ else:
173
+ trace = cast(ProgramTrace, trace_obj)
158
174
 
159
175
  for op, payload in _flatten(sequence):
160
176
  handler: HandlerFn | None = HANDLERS.get(op)
@@ -174,28 +190,34 @@ def compile_sequence(
174
190
 
175
191
 
176
192
  def seq(*tokens: Token) -> list[Token]:
193
+ """Return a mutable list of ``tokens`` for explicit sequence editing."""
194
+
177
195
  return list(tokens)
178
196
 
179
197
 
180
- def block(
181
- *tokens: Token, repeat: int = 1, close: Optional[Glyph] = None
182
- ) -> THOL:
198
+ def block(*tokens: Token, repeat: int = 1, close: Optional[Glyph] = None) -> THOL:
199
+ """Build a THOL block with optional repetition and forced closure."""
200
+
183
201
  return THOL(body=list(tokens), repeat=repeat, force_close=close)
184
202
 
185
203
 
186
- def target(nodes: Optional[Iterable[Node]] = None) -> TARGET:
204
+ def target(nodes: Optional[Iterable[NodeId]] = None) -> TARGET:
205
+ """Return a TARGET token selecting ``nodes`` (defaults to all nodes)."""
206
+
187
207
  return TARGET(nodes=nodes)
188
208
 
189
209
 
190
210
  def wait(steps: int = 1) -> WAIT:
211
+ """Return a WAIT token forcing ``steps`` structural updates before resuming."""
212
+
191
213
  return WAIT(steps=max(1, int(steps)))
192
214
 
193
215
 
194
216
  def basic_canonical_example() -> list[Token]:
195
- """Reference canonical sequence.
217
+ """Return the canonical preset sequence.
196
218
 
197
219
  Returns a copy of the canonical preset tokens to keep CLI defaults aligned
198
- with :func:`tnfr.presets.get_preset`.
220
+ with :func:`tnfr.config.presets.get_preset`.
199
221
  """
200
222
 
201
223
  return list(CANONICAL_PROGRAM_TOKENS)
tnfr/execution.pyi ADDED
@@ -0,0 +1,45 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import deque
4
+ from collections.abc import Callable, Iterable, Sequence
5
+ from typing import Any, Optional
6
+
7
+ from ._compat import TypeAlias
8
+ from .tokens import TARGET, THOL, WAIT, OpTag, Token
9
+ from .types import Glyph, NodeId, TNFRGraph
10
+
11
+ __all__: list[str]
12
+
13
+ def __getattr__(name: str) -> Any: ...
14
+
15
+ AdvanceFn = Callable[[TNFRGraph], None]
16
+ TraceEntry = dict[str, Any]
17
+ ProgramTrace: TypeAlias = deque[TraceEntry]
18
+ HandlerFn = Callable[
19
+ [TNFRGraph, Any, Sequence[NodeId] | None, ProgramTrace, AdvanceFn],
20
+ Sequence[NodeId] | None,
21
+ ]
22
+
23
+ CANONICAL_PRESET_NAME: str
24
+ CANONICAL_PROGRAM_TOKENS: tuple[Token, ...]
25
+ HANDLERS: dict[OpTag, HandlerFn]
26
+
27
+ def _apply_glyph_to_targets(
28
+ G: TNFRGraph, g: Glyph | str, nodes: Iterable[NodeId] | None = ...
29
+ ) -> None: ...
30
+ def _record_trace(
31
+ trace: ProgramTrace, G: TNFRGraph, op: OpTag, **data: Any
32
+ ) -> None: ...
33
+ def compile_sequence(
34
+ sequence: Iterable[Token] | Sequence[Token] | Any,
35
+ *,
36
+ max_materialize: int | None = ...,
37
+ ) -> list[tuple[OpTag, Any]]: ...
38
+ def play(
39
+ G: TNFRGraph, sequence: Sequence[Token], step_fn: Optional[AdvanceFn] = ...
40
+ ) -> None: ...
41
+ def seq(*tokens: Token) -> list[Token]: ...
42
+ def block(*tokens: Token, repeat: int = ..., close: Glyph | None = ...) -> THOL: ...
43
+ def target(nodes: Iterable[NodeId] | None = ...) -> TARGET: ...
44
+ def wait(steps: int = ...) -> WAIT: ...
45
+ def basic_canonical_example() -> list[Token]: ...
@@ -0,0 +1,205 @@
1
+ """Extension registry for TNFR domain extensions.
2
+
3
+ Manages registration, discovery, and access to community-contributed domain
4
+ extensions. Maintains a global registry of extensions while ensuring thread-safe
5
+ access and validation of extension requirements.
6
+ """
7
+
8
+ from typing import Dict, List, Optional, Type
9
+ from .base import TNFRExtension, PatternDefinition, CookbookRecipe
10
+
11
+
12
+ class ExtensionRegistry:
13
+ """Registry for managing TNFR domain extensions.
14
+
15
+ Provides centralized registration and discovery of domain extensions,
16
+ ensuring extensions are properly validated and accessible to the TNFR
17
+ engine and user applications.
18
+
19
+ Examples
20
+ --------
21
+ >>> from tnfr.extensions import registry
22
+ >>> from tnfr.extensions.medical import MedicalExtension
23
+ >>>
24
+ >>> # Register extension
25
+ >>> ext = MedicalExtension()
26
+ >>> registry.register_extension(ext)
27
+ >>>
28
+ >>> # List available domains
29
+ >>> domains = registry.list_extensions()
30
+ >>> print(domains) # ['medical', ...]
31
+ >>>
32
+ >>> # Get domain patterns
33
+ >>> patterns = registry.get_domain_patterns("medical")
34
+ """
35
+
36
+ def __init__(self) -> None:
37
+ """Initialize empty extension registry."""
38
+ self._extensions: Dict[str, TNFRExtension] = {}
39
+
40
+ def register_extension(self, extension: TNFRExtension) -> None:
41
+ """Register a new domain extension.
42
+
43
+ Parameters
44
+ ----------
45
+ extension : TNFRExtension
46
+ Extension instance to register.
47
+
48
+ Raises
49
+ ------
50
+ ValueError
51
+ If extension with same domain name already registered.
52
+ TypeError
53
+ If extension does not inherit from TNFRExtension.
54
+ """
55
+ if not isinstance(extension, TNFRExtension):
56
+ raise TypeError(
57
+ f"Extension must inherit from TNFRExtension, got {type(extension)}"
58
+ )
59
+
60
+ domain_name = extension.get_domain_name()
61
+
62
+ if domain_name in self._extensions:
63
+ raise ValueError(f"Extension for domain '{domain_name}' already registered")
64
+
65
+ self._extensions[domain_name] = extension
66
+
67
+ def unregister_extension(self, domain_name: str) -> None:
68
+ """Unregister an extension.
69
+
70
+ Parameters
71
+ ----------
72
+ domain_name : str
73
+ Domain name of extension to remove.
74
+
75
+ Raises
76
+ ------
77
+ KeyError
78
+ If domain not found in registry.
79
+ """
80
+ if domain_name not in self._extensions:
81
+ raise KeyError(f"Extension '{domain_name}' not found in registry")
82
+
83
+ del self._extensions[domain_name]
84
+
85
+ def get_extension(self, domain_name: str) -> Optional[TNFRExtension]:
86
+ """Get extension by domain name.
87
+
88
+ Parameters
89
+ ----------
90
+ domain_name : str
91
+ Domain name identifier.
92
+
93
+ Returns
94
+ -------
95
+ Optional[TNFRExtension]
96
+ Extension instance if found, None otherwise.
97
+ """
98
+ return self._extensions.get(domain_name)
99
+
100
+ def list_extensions(self) -> List[str]:
101
+ """List all registered extension domain names.
102
+
103
+ Returns
104
+ -------
105
+ List[str]
106
+ Sorted list of registered domain names.
107
+ """
108
+ return sorted(self._extensions.keys())
109
+
110
+ def get_domain_patterns(self, domain_name: str) -> Dict[str, PatternDefinition]:
111
+ """Get pattern definitions for a specific domain.
112
+
113
+ Parameters
114
+ ----------
115
+ domain_name : str
116
+ Domain name identifier.
117
+
118
+ Returns
119
+ -------
120
+ Dict[str, PatternDefinition]
121
+ Mapping of pattern names to definitions.
122
+
123
+ Raises
124
+ ------
125
+ KeyError
126
+ If domain not found in registry.
127
+ """
128
+ extension = self.get_extension(domain_name)
129
+ if extension is None:
130
+ raise KeyError(f"Extension '{domain_name}' not found in registry")
131
+
132
+ return extension.get_pattern_definitions()
133
+
134
+ def get_domain_health_analyzers(self, domain_name: str) -> Dict[str, Type]:
135
+ """Get health analyzers for a specific domain.
136
+
137
+ Parameters
138
+ ----------
139
+ domain_name : str
140
+ Domain name identifier.
141
+
142
+ Returns
143
+ -------
144
+ Dict[str, Type]
145
+ Mapping of analyzer names to analyzer classes.
146
+
147
+ Raises
148
+ ------
149
+ KeyError
150
+ If domain not found in registry.
151
+ """
152
+ extension = self.get_extension(domain_name)
153
+ if extension is None:
154
+ raise KeyError(f"Extension '{domain_name}' not found in registry")
155
+
156
+ return extension.get_health_analyzers()
157
+
158
+ def get_domain_recipes(self, domain_name: str) -> Dict[str, CookbookRecipe]:
159
+ """Get cookbook recipes for a specific domain.
160
+
161
+ Parameters
162
+ ----------
163
+ domain_name : str
164
+ Domain name identifier.
165
+
166
+ Returns
167
+ -------
168
+ Dict[str, CookbookRecipe]
169
+ Mapping of recipe names to recipe definitions.
170
+
171
+ Raises
172
+ ------
173
+ KeyError
174
+ If domain not found in registry.
175
+ """
176
+ extension = self.get_extension(domain_name)
177
+ if extension is None:
178
+ raise KeyError(f"Extension '{domain_name}' not found in registry")
179
+
180
+ return extension.get_cookbook_recipes()
181
+
182
+ def get_all_patterns(self) -> Dict[str, Dict[str, PatternDefinition]]:
183
+ """Get all patterns from all registered extensions.
184
+
185
+ Returns
186
+ -------
187
+ Dict[str, Dict[str, PatternDefinition]]
188
+ Nested mapping: domain_name -> pattern_name -> PatternDefinition.
189
+ """
190
+ all_patterns = {}
191
+ for domain_name, extension in self._extensions.items():
192
+ all_patterns[domain_name] = extension.get_pattern_definitions()
193
+
194
+ return all_patterns
195
+
196
+ def clear(self) -> None:
197
+ """Clear all registered extensions.
198
+
199
+ Primarily useful for testing and reinitialization.
200
+ """
201
+ self._extensions.clear()
202
+
203
+
204
+ # Global registry instance
205
+ registry = ExtensionRegistry()
@@ -0,0 +1,18 @@
1
+ """Type stubs for tnfr.extensions"""
2
+
3
+ from typing import Dict, List, Optional, Type
4
+ from .base import TNFRExtension, PatternDefinition, CookbookRecipe
5
+
6
+ class ExtensionRegistry:
7
+ def __init__(self) -> None: ...
8
+ def register_extension(self, extension: TNFRExtension) -> None: ...
9
+ def unregister_extension(self, domain_name: str) -> None: ...
10
+ def get_extension(self, domain_name: str) -> Optional[TNFRExtension]: ...
11
+ def list_extensions(self) -> List[str]: ...
12
+ def get_domain_patterns(self, domain_name: str) -> Dict[str, PatternDefinition]: ...
13
+ def get_domain_health_analyzers(self, domain_name: str) -> Dict[str, Type]: ...
14
+ def get_domain_recipes(self, domain_name: str) -> Dict[str, CookbookRecipe]: ...
15
+ def get_all_patterns(self) -> Dict[str, Dict[str, PatternDefinition]]: ...
16
+ def clear(self) -> None: ...
17
+
18
+ registry: ExtensionRegistry
@@ -0,0 +1,173 @@
1
+ """Base classes for TNFR domain extensions.
2
+
3
+ This module provides the foundation for community-contributed domain extensions
4
+ to TNFR Grammar 2.0. Extensions allow domain experts to add specialized patterns,
5
+ health analyzers, and tools while maintaining canonical TNFR invariants.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from dataclasses import dataclass, field
10
+ from typing import Any, Dict, List, Optional, Type
11
+
12
+
13
+ @dataclass
14
+ class PatternDefinition:
15
+ """Definition of a domain-specific structural pattern.
16
+
17
+ Captures a validated sequence of structural operators and its domain context,
18
+ ensuring patterns maintain TNFR canonical requirements while providing
19
+ domain-specific semantics.
20
+
21
+ Attributes
22
+ ----------
23
+ name : str
24
+ Unique identifier for the pattern within its domain.
25
+ sequence : List[str]
26
+ Ordered list of structural operator identifiers.
27
+ description : str
28
+ Human-readable explanation of what the pattern achieves.
29
+ use_cases : List[str]
30
+ Real-world scenarios where this pattern applies.
31
+ health_requirements : Dict[str, float]
32
+ Minimum health metrics (C(t), Si) required for pattern validity.
33
+ domain_context : Dict[str, Any]
34
+ Domain-specific metadata explaining real-world mapping.
35
+ examples : List[Dict[str, Any]]
36
+ Validated examples demonstrating pattern effectiveness.
37
+ """
38
+
39
+ name: str
40
+ sequence: List[str]
41
+ description: str
42
+ use_cases: List[str] = field(default_factory=list)
43
+ health_requirements: Dict[str, float] = field(default_factory=dict)
44
+ domain_context: Dict[str, Any] = field(default_factory=dict)
45
+ examples: List[Dict[str, Any]] = field(default_factory=list)
46
+
47
+
48
+ @dataclass
49
+ class CookbookRecipe:
50
+ """Validated recipe for a common domain scenario.
51
+
52
+ Provides a tested sequence configuration with parameters and expected outcomes,
53
+ allowing practitioners to apply proven patterns to their specific contexts.
54
+
55
+ Attributes
56
+ ----------
57
+ name : str
58
+ Unique identifier for the recipe.
59
+ description : str
60
+ What this recipe achieves in domain terms.
61
+ sequence : List[str]
62
+ Structural operator sequence.
63
+ parameters : Dict[str, Any]
64
+ Recommended parameters (νf, phase, etc.).
65
+ expected_health : Dict[str, float]
66
+ Expected health metrics (C(t), Si) for successful application.
67
+ validation : Dict[str, Any]
68
+ Validation metadata (test count, success rate, notes).
69
+ """
70
+
71
+ name: str
72
+ description: str
73
+ sequence: List[str]
74
+ parameters: Dict[str, Any] = field(default_factory=dict)
75
+ expected_health: Dict[str, float] = field(default_factory=dict)
76
+ validation: Dict[str, Any] = field(default_factory=dict)
77
+
78
+
79
+ class TNFRExtension(ABC):
80
+ """Abstract base class for TNFR domain extensions.
81
+
82
+ Domain extensions provide specialized patterns, health analyzers, and tools
83
+ for specific application domains while maintaining TNFR canonical invariants.
84
+ All extensions must implement the core abstract methods to ensure consistent
85
+ structure and discoverability.
86
+
87
+ Examples
88
+ --------
89
+ >>> class MedicalExtension(TNFRExtension):
90
+ ... def get_domain_name(self) -> str:
91
+ ... return "medical"
92
+ ...
93
+ ... def get_pattern_definitions(self) -> Dict[str, PatternDefinition]:
94
+ ... return {
95
+ ... "therapeutic_alliance": PatternDefinition(
96
+ ... name="therapeutic_alliance",
97
+ ... sequence=["emission", "reception", "coherence"],
98
+ ... description="Establishing therapeutic trust",
99
+ ... use_cases=["Initial therapy session", "Crisis intervention"],
100
+ ... )
101
+ ... }
102
+ ...
103
+ ... def get_health_analyzers(self) -> Dict[str, Type]:
104
+ ... from .health_analyzers import TherapeuticHealthAnalyzer
105
+ ... return {"therapeutic": TherapeuticHealthAnalyzer}
106
+ """
107
+
108
+ @abstractmethod
109
+ def get_domain_name(self) -> str:
110
+ """Return the unique domain identifier.
111
+
112
+ Returns
113
+ -------
114
+ str
115
+ Domain name (lowercase, underscore-separated).
116
+ """
117
+ pass
118
+
119
+ @abstractmethod
120
+ def get_pattern_definitions(self) -> Dict[str, PatternDefinition]:
121
+ """Return domain-specific pattern definitions.
122
+
123
+ Returns
124
+ -------
125
+ Dict[str, PatternDefinition]
126
+ Mapping of pattern names to their definitions.
127
+ """
128
+ pass
129
+
130
+ @abstractmethod
131
+ def get_health_analyzers(self) -> Dict[str, Type]:
132
+ """Return domain-specific health analyzer classes.
133
+
134
+ Returns
135
+ -------
136
+ Dict[str, Type]
137
+ Mapping of analyzer names to analyzer classes.
138
+ """
139
+ pass
140
+
141
+ def get_cookbook_recipes(self) -> Dict[str, CookbookRecipe]:
142
+ """Return validated recipes for common scenarios.
143
+
144
+ Returns
145
+ -------
146
+ Dict[str, CookbookRecipe]
147
+ Mapping of recipe names to recipe definitions. Empty dict if none.
148
+ """
149
+ return {}
150
+
151
+ def get_visualization_tools(self) -> Dict[str, Type]:
152
+ """Return domain-specific visualization tools.
153
+
154
+ Returns
155
+ -------
156
+ Dict[str, Type]
157
+ Mapping of visualizer names to visualizer classes. Empty dict if none.
158
+ """
159
+ return {}
160
+
161
+ def get_metadata(self) -> Dict[str, Any]:
162
+ """Return extension metadata.
163
+
164
+ Returns
165
+ -------
166
+ Dict[str, Any]
167
+ Metadata including version, author, description, etc.
168
+ """
169
+ return {
170
+ "domain": self.get_domain_name(),
171
+ "version": "1.0.0",
172
+ "description": self.__doc__ or "No description provided",
173
+ }