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
@@ -0,0 +1,492 @@
1
+ """Contextual error handling for TNFR operations.
2
+
3
+ This module provides enhanced error messages that guide users to solutions
4
+ while maintaining TNFR theoretical compliance. All errors include:
5
+
6
+ 1. Clear explanation of the violation
7
+ 2. Actionable suggestions for resolution
8
+ 3. Links to relevant documentation
9
+ 4. Context about the structural operation that failed
10
+
11
+ Canonical Invariants Preserved
12
+ ------------------------------
13
+ These errors enforce TNFR invariants from AGENTS.md:
14
+ - Operator closure and sequence validity
15
+ - Phase synchrony requirements for coupling
16
+ - Frequency (νf) bounds in Hz_str units
17
+ - ΔNFR semantic correctness
18
+ - EPI coherence preservation
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from difflib import get_close_matches
24
+ from typing import Optional, List, Dict, Any
25
+
26
+ __all__ = [
27
+ "TNFRUserError",
28
+ "OperatorSequenceError",
29
+ "NetworkConfigError",
30
+ "PhaseError",
31
+ "CoherenceError",
32
+ "FrequencyError",
33
+ ]
34
+
35
+
36
+ class TNFRUserError(Exception):
37
+ """Base class for user-facing TNFR errors with helpful context.
38
+
39
+ All TNFR errors inherit from this class and provide:
40
+ - Human-readable error messages
41
+ - Actionable suggestions
42
+ - Documentation links
43
+ - Structural context
44
+
45
+ Parameters
46
+ ----------
47
+ message : str
48
+ Primary error message describing what went wrong.
49
+ suggestion : str, optional
50
+ Specific suggestion for how to fix the issue.
51
+ docs_url : str, optional
52
+ URL to relevant documentation section.
53
+ context : dict, optional
54
+ Additional context about the failed operation (node IDs, values, etc).
55
+
56
+ Examples
57
+ --------
58
+ >>> raise TNFRUserError(
59
+ ... "Invalid structural frequency",
60
+ ... suggestion="νf must be positive in Hz_str units",
61
+ ... docs_url="https://tnfr.readthedocs.io/api/core.html#frequency"
62
+ ... )
63
+ """
64
+
65
+ def __init__(
66
+ self,
67
+ message: str,
68
+ suggestion: Optional[str] = None,
69
+ docs_url: Optional[str] = None,
70
+ context: Optional[Dict[str, Any]] = None,
71
+ ):
72
+ self.message = message
73
+ self.suggestion = suggestion
74
+ self.docs_url = docs_url
75
+ self.context = context or {}
76
+
77
+ # Build comprehensive error message
78
+ full_message = f"\n{'='*70}\n"
79
+ full_message += f"TNFR Error: {message}\n"
80
+ full_message += f"{'='*70}\n"
81
+
82
+ if suggestion:
83
+ full_message += f"\n💡 Suggestion: {suggestion}\n"
84
+
85
+ if context:
86
+ full_message += f"\n📊 Context:\n"
87
+ for key, value in context.items():
88
+ full_message += f" • {key}: {value}\n"
89
+
90
+ if docs_url:
91
+ full_message += f"\n📚 Documentation: {docs_url}\n"
92
+
93
+ full_message += f"{'='*70}\n"
94
+
95
+ super().__init__(full_message)
96
+
97
+
98
+ class OperatorSequenceError(TNFRUserError):
99
+ """Error raised when operator sequence violates TNFR grammar.
100
+
101
+ TNFR operators must be applied in valid sequences that respect
102
+ structural coherence. This error provides:
103
+ - The invalid sequence attempted
104
+ - Which operator violated the grammar
105
+ - Valid next operators
106
+ - Fuzzy matching for typos
107
+
108
+ Enforces Invariant #4: Operator closure from AGENTS.md
109
+
110
+ Parameters
111
+ ----------
112
+ invalid_operator : str
113
+ The operator that violated the grammar.
114
+ sequence_so_far : list of str
115
+ Operators successfully applied before the error.
116
+ valid_next : list of str, optional
117
+ Valid operators that can follow the current sequence.
118
+
119
+ Examples
120
+ --------
121
+ >>> raise OperatorSequenceError(
122
+ ... "emision",
123
+ ... ["reception", "coherence"],
124
+ ... ["emission", "recursivity"]
125
+ ... )
126
+ """
127
+
128
+ # Valid TNFR operators (13 canonical operators)
129
+ VALID_OPERATORS = {
130
+ "emission",
131
+ "reception",
132
+ "coherence",
133
+ "dissonance",
134
+ "coupling",
135
+ "resonance",
136
+ "silence",
137
+ "expansion",
138
+ "contraction",
139
+ "self_organization",
140
+ "mutation",
141
+ "transition",
142
+ "recursivity",
143
+ }
144
+
145
+ # Operator aliases for user convenience
146
+ OPERATOR_ALIASES = {
147
+ "emit": "emission",
148
+ "receive": "reception",
149
+ "cohere": "coherence",
150
+ "couple": "coupling",
151
+ "resonate": "resonance",
152
+ "silent": "silence",
153
+ "expand": "expansion",
154
+ "contract": "contraction",
155
+ "self_organize": "self_organization",
156
+ "mutate": "mutation",
157
+ "recurse": "recursivity",
158
+ }
159
+
160
+ def __init__(
161
+ self,
162
+ invalid_operator: str,
163
+ sequence_so_far: Optional[List[str]] = None,
164
+ valid_next: Optional[List[str]] = None,
165
+ ):
166
+ sequence_so_far = sequence_so_far or []
167
+
168
+ # Try fuzzy matching for typos
169
+ all_valid = list(self.VALID_OPERATORS) + list(self.OPERATOR_ALIASES.keys())
170
+ matches = get_close_matches(invalid_operator, all_valid, n=3, cutoff=0.6)
171
+
172
+ suggestion_parts = []
173
+ if matches:
174
+ suggestion_parts.append(f"Did you mean one of: {', '.join(matches)}?")
175
+
176
+ if valid_next:
177
+ suggestion_parts.append(f"Valid next operators: {', '.join(valid_next)}")
178
+ else:
179
+ suggestion_parts.append(
180
+ f"Use one of the 13 canonical operators: "
181
+ f"{', '.join(sorted(self.VALID_OPERATORS))}"
182
+ )
183
+
184
+ suggestion = " ".join(suggestion_parts) if suggestion_parts else None
185
+
186
+ context = {
187
+ "invalid_operator": invalid_operator,
188
+ "sequence_so_far": (
189
+ " → ".join(sequence_so_far) if sequence_so_far else "empty"
190
+ ),
191
+ "operator_count": len(sequence_so_far),
192
+ }
193
+
194
+ super().__init__(
195
+ message=f"Invalid operator sequence: '{invalid_operator}' cannot be applied",
196
+ suggestion=suggestion,
197
+ docs_url="https://github.com/fermga/Teoria-de-la-naturaleza-fractal-resonante-TNFR-/blob/main/docs/source/api/operators.md",
198
+ context=context,
199
+ )
200
+
201
+
202
+ class NetworkConfigError(TNFRUserError):
203
+ """Error raised when network configuration violates TNFR constraints.
204
+
205
+ This error validates configuration parameters and provides valid ranges
206
+ with physical/structural meaning.
207
+
208
+ Enforces multiple invariants:
209
+ - Invariant #2: Structural units (νf in Hz_str)
210
+ - Invariant #5: Phase check requirements
211
+ - Invariant #6: Node birth/collapse conditions
212
+
213
+ Parameters
214
+ ----------
215
+ parameter : str
216
+ The configuration parameter that is invalid.
217
+ value : any
218
+ The invalid value provided.
219
+ valid_range : tuple, optional
220
+ Valid range for the parameter (min, max).
221
+ reason : str, optional
222
+ Structural reason for the constraint.
223
+
224
+ Examples
225
+ --------
226
+ >>> raise NetworkConfigError(
227
+ ... "vf",
228
+ ... -0.5,
229
+ ... (0.01, 100.0),
230
+ ... "Structural frequency must be positive (Hz_str units)"
231
+ ... )
232
+ """
233
+
234
+ # Valid parameter ranges with structural meaning
235
+ PARAMETER_CONSTRAINTS = {
236
+ "vf": {
237
+ "range": (0.01, 100.0),
238
+ "unit": "Hz_str",
239
+ "description": "Structural frequency (reorganization rate)",
240
+ },
241
+ "phase": {
242
+ "range": (0.0, 2 * 3.14159),
243
+ "unit": "radians",
244
+ "description": "Phase angle for network synchrony",
245
+ },
246
+ "coherence": {
247
+ "range": (0.0, 1.0),
248
+ "unit": "dimensionless",
249
+ "description": "Structural stability measure C(t)",
250
+ },
251
+ "delta_nfr": {
252
+ "range": (-10.0, 10.0),
253
+ "unit": "dimensionless",
254
+ "description": "Internal reorganization gradient ΔNFR",
255
+ },
256
+ "epi": {
257
+ "range": (0.0, 1.0),
258
+ "unit": "dimensionless",
259
+ "description": "Primary Information Structure magnitude",
260
+ },
261
+ "edge_probability": {
262
+ "range": (0.0, 1.0),
263
+ "unit": "probability",
264
+ "description": "Network edge connection probability",
265
+ },
266
+ "num_nodes": {
267
+ "range": (1, 100000),
268
+ "unit": "count",
269
+ "description": "Number of nodes in network",
270
+ },
271
+ }
272
+
273
+ def __init__(
274
+ self,
275
+ parameter: str,
276
+ value: Any,
277
+ valid_range: Optional[tuple] = None,
278
+ reason: Optional[str] = None,
279
+ ):
280
+ # Get constraint info if available
281
+ constraint_info = self.PARAMETER_CONSTRAINTS.get(parameter)
282
+
283
+ if constraint_info and not valid_range:
284
+ valid_range = constraint_info["range"]
285
+ reason = reason or constraint_info["description"]
286
+
287
+ suggestion_parts = []
288
+ if valid_range:
289
+ min_val, max_val = valid_range
290
+ suggestion_parts.append(
291
+ f"'{parameter}' must be in range [{min_val}, {max_val}]"
292
+ )
293
+
294
+ if constraint_info:
295
+ suggestion_parts.append(f"Unit: {constraint_info['unit']}")
296
+
297
+ if reason:
298
+ suggestion_parts.append(f"Structural meaning: {reason}")
299
+
300
+ context = {
301
+ "parameter": parameter,
302
+ "provided_value": value,
303
+ "valid_range": (
304
+ f"[{valid_range[0]}, {valid_range[1]}]" if valid_range else "see docs"
305
+ ),
306
+ }
307
+
308
+ super().__init__(
309
+ message=f"Invalid network configuration for '{parameter}'",
310
+ suggestion=" | ".join(suggestion_parts) if suggestion_parts else None,
311
+ docs_url="https://github.com/fermga/Teoria-de-la-naturaleza-fractal-resonante-TNFR-/blob/main/docs/source/api/overview.md",
312
+ context=context,
313
+ )
314
+
315
+
316
+ class PhaseError(TNFRUserError):
317
+ """Error raised when phase synchrony is violated.
318
+
319
+ TNFR requires explicit phase checking before coupling operations.
320
+ This error indicates phase incompatibility between nodes.
321
+
322
+ Enforces Invariant #5: Phase check from AGENTS.md
323
+
324
+ Parameters
325
+ ----------
326
+ node1 : str
327
+ First node ID.
328
+ node2 : str
329
+ Second node ID.
330
+ phase1 : float
331
+ Phase of first node (radians).
332
+ phase2 : float
333
+ Phase of second node (radians).
334
+ threshold : float
335
+ Phase difference threshold for coupling.
336
+
337
+ Examples
338
+ --------
339
+ >>> raise PhaseError("n1", "n2", 0.5, 2.8, 0.5)
340
+ """
341
+
342
+ def __init__(
343
+ self,
344
+ node1: str,
345
+ node2: str,
346
+ phase1: float,
347
+ phase2: float,
348
+ threshold: float = 0.5,
349
+ ):
350
+ phase_diff = abs(phase1 - phase2)
351
+
352
+ suggestion = (
353
+ f"Nodes cannot couple: phase difference ({phase_diff:.3f} rad) "
354
+ f"exceeds threshold ({threshold:.3f} rad). "
355
+ f"Apply phase synchronization or adjust threshold."
356
+ )
357
+
358
+ context = {
359
+ "node1": node1,
360
+ "node2": node2,
361
+ "phase1": f"{phase1:.3f} rad",
362
+ "phase2": f"{phase2:.3f} rad",
363
+ "phase_difference": f"{phase_diff:.3f} rad",
364
+ "threshold": f"{threshold:.3f} rad",
365
+ }
366
+
367
+ super().__init__(
368
+ message=f"Phase synchrony violation between nodes '{node1}' and '{node2}'",
369
+ suggestion=suggestion,
370
+ docs_url="https://github.com/fermga/Teoria-de-la-naturaleza-fractal-resonante-TNFR-/blob/main/GLOSSARY.md#phase",
371
+ context=context,
372
+ )
373
+
374
+
375
+ class CoherenceError(TNFRUserError):
376
+ """Error raised when coherence operations violate monotonicity.
377
+
378
+ Coherence operator must not decrease C(t) except in controlled
379
+ dissonance tests. This error indicates unexpected coherence loss.
380
+
381
+ Enforces Invariant #1: EPI coherent form from AGENTS.md
382
+
383
+ Parameters
384
+ ----------
385
+ operation : str
386
+ The operation that caused coherence decrease.
387
+ before : float
388
+ Coherence C(t) before operation.
389
+ after : float
390
+ Coherence C(t) after operation.
391
+ node_id : str, optional
392
+ Node ID if the error is node-specific.
393
+
394
+ Examples
395
+ --------
396
+ >>> raise CoherenceError("coherence", 0.85, 0.42)
397
+ """
398
+
399
+ def __init__(
400
+ self,
401
+ operation: str,
402
+ before: float,
403
+ after: float,
404
+ node_id: Optional[str] = None,
405
+ ):
406
+ decrease = before - after
407
+ percent_loss = (decrease / before * 100) if before > 0 else 0
408
+
409
+ suggestion = (
410
+ f"Coherence decreased by {decrease:.3f} ({percent_loss:.1f}%). "
411
+ f"This violates the coherence monotonicity invariant. "
412
+ f"Check if this is a controlled dissonance test or if "
413
+ f"there's an unexpected structural instability."
414
+ )
415
+
416
+ context = {
417
+ "operation": operation,
418
+ "coherence_before": f"{before:.3f}",
419
+ "coherence_after": f"{after:.3f}",
420
+ "decrease": f"{decrease:.3f}",
421
+ "percent_loss": f"{percent_loss:.1f}%",
422
+ }
423
+
424
+ if node_id:
425
+ context["node_id"] = node_id
426
+
427
+ super().__init__(
428
+ message=f"Unexpected coherence decrease during '{operation}'",
429
+ suggestion=suggestion,
430
+ docs_url="https://github.com/fermga/Teoria-de-la-naturaleza-fractal-resonante-TNFR-/blob/main/AGENTS.md#canonical-invariants",
431
+ context=context,
432
+ )
433
+
434
+
435
+ class FrequencyError(TNFRUserError):
436
+ """Error raised when structural frequency νf is invalid.
437
+
438
+ Structural frequency must be positive and expressed in Hz_str
439
+ (structural hertz) units. This error indicates frequency violations.
440
+
441
+ Enforces Invariant #2: Structural units from AGENTS.md
442
+
443
+ Parameters
444
+ ----------
445
+ node_id : str
446
+ Node ID with invalid frequency.
447
+ vf : float
448
+ The invalid frequency value.
449
+ operation : str, optional
450
+ Operation that triggered the check.
451
+
452
+ Examples
453
+ --------
454
+ >>> raise FrequencyError("n1", -0.5, "emission")
455
+ """
456
+
457
+ def __init__(
458
+ self,
459
+ node_id: str,
460
+ vf: float,
461
+ operation: Optional[str] = None,
462
+ ):
463
+ if vf <= 0:
464
+ suggestion = (
465
+ f"Structural frequency νf must be positive (Hz_str units). "
466
+ f"Set νf > 0 for node '{node_id}'. "
467
+ f"Typical range: 0.1 to 10.0 Hz_str."
468
+ )
469
+ elif vf > 100:
470
+ suggestion = (
471
+ f"Structural frequency νf = {vf:.3f} Hz_str is very high. "
472
+ f"Typical range: 0.1 to 10.0 Hz_str. "
473
+ f"Verify this is intentional."
474
+ )
475
+ else:
476
+ suggestion = f"Verify structural frequency for node '{node_id}'."
477
+
478
+ context = {
479
+ "node_id": node_id,
480
+ "vf": f"{vf:.3f} Hz_str",
481
+ "valid_range": "[0.01, 100.0] Hz_str",
482
+ }
483
+
484
+ if operation:
485
+ context["operation"] = operation
486
+
487
+ super().__init__(
488
+ message=f"Invalid structural frequency for node '{node_id}'",
489
+ suggestion=suggestion,
490
+ docs_url="https://github.com/fermga/Teoria-de-la-naturaleza-fractal-resonante-TNFR-/blob/main/GLOSSARY.md#structural-frequency",
491
+ context=context,
492
+ )