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

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

Potentially problematic release.


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

Files changed (360) hide show
  1. tnfr/__init__.py +375 -56
  2. tnfr/__init__.pyi +33 -0
  3. tnfr/_compat.py +10 -0
  4. tnfr/_generated_version.py +34 -0
  5. tnfr/_version.py +49 -0
  6. tnfr/_version.pyi +7 -0
  7. tnfr/alias.py +723 -0
  8. tnfr/alias.pyi +108 -0
  9. tnfr/backends/__init__.py +354 -0
  10. tnfr/backends/jax_backend.py +173 -0
  11. tnfr/backends/numpy_backend.py +238 -0
  12. tnfr/backends/optimized_numpy.py +420 -0
  13. tnfr/backends/torch_backend.py +408 -0
  14. tnfr/cache.py +171 -0
  15. tnfr/cache.pyi +13 -0
  16. tnfr/cli/__init__.py +110 -0
  17. tnfr/cli/__init__.pyi +26 -0
  18. tnfr/cli/arguments.py +489 -0
  19. tnfr/cli/arguments.pyi +29 -0
  20. tnfr/cli/execution.py +914 -0
  21. tnfr/cli/execution.pyi +70 -0
  22. tnfr/cli/interactive_validator.py +614 -0
  23. tnfr/cli/utils.py +51 -0
  24. tnfr/cli/utils.pyi +7 -0
  25. tnfr/cli/validate.py +236 -0
  26. tnfr/compat/__init__.py +85 -0
  27. tnfr/compat/dataclass.py +136 -0
  28. tnfr/compat/jsonschema_stub.py +61 -0
  29. tnfr/compat/matplotlib_stub.py +73 -0
  30. tnfr/compat/numpy_stub.py +155 -0
  31. tnfr/config/__init__.py +224 -0
  32. tnfr/config/__init__.pyi +10 -0
  33. tnfr/config/constants.py +104 -0
  34. tnfr/config/constants.pyi +12 -0
  35. tnfr/config/defaults.py +54 -0
  36. tnfr/config/defaults_core.py +212 -0
  37. tnfr/config/defaults_init.py +33 -0
  38. tnfr/config/defaults_metric.py +104 -0
  39. tnfr/config/feature_flags.py +81 -0
  40. tnfr/config/feature_flags.pyi +16 -0
  41. tnfr/config/glyph_constants.py +31 -0
  42. tnfr/config/init.py +77 -0
  43. tnfr/config/init.pyi +8 -0
  44. tnfr/config/operator_names.py +254 -0
  45. tnfr/config/operator_names.pyi +36 -0
  46. tnfr/config/physics_derivation.py +354 -0
  47. tnfr/config/presets.py +83 -0
  48. tnfr/config/presets.pyi +7 -0
  49. tnfr/config/security.py +927 -0
  50. tnfr/config/thresholds.py +114 -0
  51. tnfr/config/tnfr_config.py +498 -0
  52. tnfr/constants/__init__.py +92 -0
  53. tnfr/constants/__init__.pyi +92 -0
  54. tnfr/constants/aliases.py +33 -0
  55. tnfr/constants/aliases.pyi +27 -0
  56. tnfr/constants/init.py +33 -0
  57. tnfr/constants/init.pyi +12 -0
  58. tnfr/constants/metric.py +104 -0
  59. tnfr/constants/metric.pyi +19 -0
  60. tnfr/core/__init__.py +33 -0
  61. tnfr/core/container.py +226 -0
  62. tnfr/core/default_implementations.py +329 -0
  63. tnfr/core/interfaces.py +279 -0
  64. tnfr/dynamics/__init__.py +238 -0
  65. tnfr/dynamics/__init__.pyi +83 -0
  66. tnfr/dynamics/adaptation.py +267 -0
  67. tnfr/dynamics/adaptation.pyi +7 -0
  68. tnfr/dynamics/adaptive_sequences.py +189 -0
  69. tnfr/dynamics/adaptive_sequences.pyi +14 -0
  70. tnfr/dynamics/aliases.py +23 -0
  71. tnfr/dynamics/aliases.pyi +19 -0
  72. tnfr/dynamics/bifurcation.py +232 -0
  73. tnfr/dynamics/canonical.py +229 -0
  74. tnfr/dynamics/canonical.pyi +48 -0
  75. tnfr/dynamics/coordination.py +385 -0
  76. tnfr/dynamics/coordination.pyi +25 -0
  77. tnfr/dynamics/dnfr.py +3034 -0
  78. tnfr/dynamics/dnfr.pyi +26 -0
  79. tnfr/dynamics/dynamic_limits.py +225 -0
  80. tnfr/dynamics/feedback.py +252 -0
  81. tnfr/dynamics/feedback.pyi +24 -0
  82. tnfr/dynamics/fused_dnfr.py +454 -0
  83. tnfr/dynamics/homeostasis.py +157 -0
  84. tnfr/dynamics/homeostasis.pyi +14 -0
  85. tnfr/dynamics/integrators.py +661 -0
  86. tnfr/dynamics/integrators.pyi +36 -0
  87. tnfr/dynamics/learning.py +310 -0
  88. tnfr/dynamics/learning.pyi +33 -0
  89. tnfr/dynamics/metabolism.py +254 -0
  90. tnfr/dynamics/nbody.py +796 -0
  91. tnfr/dynamics/nbody_tnfr.py +783 -0
  92. tnfr/dynamics/propagation.py +326 -0
  93. tnfr/dynamics/runtime.py +908 -0
  94. tnfr/dynamics/runtime.pyi +77 -0
  95. tnfr/dynamics/sampling.py +36 -0
  96. tnfr/dynamics/sampling.pyi +7 -0
  97. tnfr/dynamics/selectors.py +711 -0
  98. tnfr/dynamics/selectors.pyi +85 -0
  99. tnfr/dynamics/structural_clip.py +207 -0
  100. tnfr/errors/__init__.py +37 -0
  101. tnfr/errors/contextual.py +492 -0
  102. tnfr/execution.py +223 -0
  103. tnfr/execution.pyi +45 -0
  104. tnfr/extensions/__init__.py +205 -0
  105. tnfr/extensions/__init__.pyi +18 -0
  106. tnfr/extensions/base.py +173 -0
  107. tnfr/extensions/base.pyi +35 -0
  108. tnfr/extensions/business/__init__.py +71 -0
  109. tnfr/extensions/business/__init__.pyi +11 -0
  110. tnfr/extensions/business/cookbook.py +88 -0
  111. tnfr/extensions/business/cookbook.pyi +8 -0
  112. tnfr/extensions/business/health_analyzers.py +202 -0
  113. tnfr/extensions/business/health_analyzers.pyi +9 -0
  114. tnfr/extensions/business/patterns.py +183 -0
  115. tnfr/extensions/business/patterns.pyi +8 -0
  116. tnfr/extensions/medical/__init__.py +73 -0
  117. tnfr/extensions/medical/__init__.pyi +11 -0
  118. tnfr/extensions/medical/cookbook.py +88 -0
  119. tnfr/extensions/medical/cookbook.pyi +8 -0
  120. tnfr/extensions/medical/health_analyzers.py +181 -0
  121. tnfr/extensions/medical/health_analyzers.pyi +9 -0
  122. tnfr/extensions/medical/patterns.py +163 -0
  123. tnfr/extensions/medical/patterns.pyi +8 -0
  124. tnfr/flatten.py +262 -0
  125. tnfr/flatten.pyi +21 -0
  126. tnfr/gamma.py +354 -0
  127. tnfr/gamma.pyi +36 -0
  128. tnfr/glyph_history.py +377 -0
  129. tnfr/glyph_history.pyi +35 -0
  130. tnfr/glyph_runtime.py +19 -0
  131. tnfr/glyph_runtime.pyi +8 -0
  132. tnfr/immutable.py +218 -0
  133. tnfr/immutable.pyi +36 -0
  134. tnfr/initialization.py +203 -0
  135. tnfr/initialization.pyi +65 -0
  136. tnfr/io.py +10 -0
  137. tnfr/io.pyi +13 -0
  138. tnfr/locking.py +37 -0
  139. tnfr/locking.pyi +7 -0
  140. tnfr/mathematics/__init__.py +79 -0
  141. tnfr/mathematics/backend.py +453 -0
  142. tnfr/mathematics/backend.pyi +99 -0
  143. tnfr/mathematics/dynamics.py +408 -0
  144. tnfr/mathematics/dynamics.pyi +90 -0
  145. tnfr/mathematics/epi.py +391 -0
  146. tnfr/mathematics/epi.pyi +65 -0
  147. tnfr/mathematics/generators.py +242 -0
  148. tnfr/mathematics/generators.pyi +29 -0
  149. tnfr/mathematics/metrics.py +119 -0
  150. tnfr/mathematics/metrics.pyi +16 -0
  151. tnfr/mathematics/operators.py +239 -0
  152. tnfr/mathematics/operators.pyi +59 -0
  153. tnfr/mathematics/operators_factory.py +124 -0
  154. tnfr/mathematics/operators_factory.pyi +11 -0
  155. tnfr/mathematics/projection.py +87 -0
  156. tnfr/mathematics/projection.pyi +33 -0
  157. tnfr/mathematics/runtime.py +182 -0
  158. tnfr/mathematics/runtime.pyi +64 -0
  159. tnfr/mathematics/spaces.py +256 -0
  160. tnfr/mathematics/spaces.pyi +83 -0
  161. tnfr/mathematics/transforms.py +305 -0
  162. tnfr/mathematics/transforms.pyi +62 -0
  163. tnfr/metrics/__init__.py +79 -0
  164. tnfr/metrics/__init__.pyi +20 -0
  165. tnfr/metrics/buffer_cache.py +163 -0
  166. tnfr/metrics/buffer_cache.pyi +24 -0
  167. tnfr/metrics/cache_utils.py +214 -0
  168. tnfr/metrics/coherence.py +2009 -0
  169. tnfr/metrics/coherence.pyi +129 -0
  170. tnfr/metrics/common.py +158 -0
  171. tnfr/metrics/common.pyi +35 -0
  172. tnfr/metrics/core.py +316 -0
  173. tnfr/metrics/core.pyi +13 -0
  174. tnfr/metrics/diagnosis.py +833 -0
  175. tnfr/metrics/diagnosis.pyi +86 -0
  176. tnfr/metrics/emergence.py +245 -0
  177. tnfr/metrics/export.py +179 -0
  178. tnfr/metrics/export.pyi +7 -0
  179. tnfr/metrics/glyph_timing.py +379 -0
  180. tnfr/metrics/glyph_timing.pyi +81 -0
  181. tnfr/metrics/learning_metrics.py +280 -0
  182. tnfr/metrics/learning_metrics.pyi +21 -0
  183. tnfr/metrics/phase_coherence.py +351 -0
  184. tnfr/metrics/phase_compatibility.py +349 -0
  185. tnfr/metrics/reporting.py +183 -0
  186. tnfr/metrics/reporting.pyi +25 -0
  187. tnfr/metrics/sense_index.py +1203 -0
  188. tnfr/metrics/sense_index.pyi +9 -0
  189. tnfr/metrics/trig.py +373 -0
  190. tnfr/metrics/trig.pyi +13 -0
  191. tnfr/metrics/trig_cache.py +233 -0
  192. tnfr/metrics/trig_cache.pyi +10 -0
  193. tnfr/multiscale/__init__.py +32 -0
  194. tnfr/multiscale/hierarchical.py +517 -0
  195. tnfr/node.py +763 -0
  196. tnfr/node.pyi +139 -0
  197. tnfr/observers.py +255 -130
  198. tnfr/observers.pyi +31 -0
  199. tnfr/ontosim.py +144 -137
  200. tnfr/ontosim.pyi +28 -0
  201. tnfr/operators/__init__.py +1672 -0
  202. tnfr/operators/__init__.pyi +31 -0
  203. tnfr/operators/algebra.py +277 -0
  204. tnfr/operators/canonical_patterns.py +420 -0
  205. tnfr/operators/cascade.py +267 -0
  206. tnfr/operators/cycle_detection.py +358 -0
  207. tnfr/operators/definitions.py +4108 -0
  208. tnfr/operators/definitions.pyi +78 -0
  209. tnfr/operators/grammar.py +1164 -0
  210. tnfr/operators/grammar.pyi +140 -0
  211. tnfr/operators/hamiltonian.py +710 -0
  212. tnfr/operators/health_analyzer.py +809 -0
  213. tnfr/operators/jitter.py +272 -0
  214. tnfr/operators/jitter.pyi +11 -0
  215. tnfr/operators/lifecycle.py +314 -0
  216. tnfr/operators/metabolism.py +618 -0
  217. tnfr/operators/metrics.py +2138 -0
  218. tnfr/operators/network_analysis/__init__.py +27 -0
  219. tnfr/operators/network_analysis/source_detection.py +186 -0
  220. tnfr/operators/nodal_equation.py +395 -0
  221. tnfr/operators/pattern_detection.py +660 -0
  222. tnfr/operators/patterns.py +669 -0
  223. tnfr/operators/postconditions/__init__.py +38 -0
  224. tnfr/operators/postconditions/mutation.py +236 -0
  225. tnfr/operators/preconditions/__init__.py +1226 -0
  226. tnfr/operators/preconditions/coherence.py +305 -0
  227. tnfr/operators/preconditions/dissonance.py +236 -0
  228. tnfr/operators/preconditions/emission.py +128 -0
  229. tnfr/operators/preconditions/mutation.py +580 -0
  230. tnfr/operators/preconditions/reception.py +125 -0
  231. tnfr/operators/preconditions/resonance.py +364 -0
  232. tnfr/operators/registry.py +74 -0
  233. tnfr/operators/registry.pyi +9 -0
  234. tnfr/operators/remesh.py +1809 -0
  235. tnfr/operators/remesh.pyi +26 -0
  236. tnfr/operators/structural_units.py +268 -0
  237. tnfr/operators/unified_grammar.py +105 -0
  238. tnfr/parallel/__init__.py +54 -0
  239. tnfr/parallel/auto_scaler.py +234 -0
  240. tnfr/parallel/distributed.py +384 -0
  241. tnfr/parallel/engine.py +238 -0
  242. tnfr/parallel/gpu_engine.py +420 -0
  243. tnfr/parallel/monitoring.py +248 -0
  244. tnfr/parallel/partitioner.py +459 -0
  245. tnfr/py.typed +0 -0
  246. tnfr/recipes/__init__.py +22 -0
  247. tnfr/recipes/cookbook.py +743 -0
  248. tnfr/rng.py +178 -0
  249. tnfr/rng.pyi +26 -0
  250. tnfr/schemas/__init__.py +8 -0
  251. tnfr/schemas/grammar.json +94 -0
  252. tnfr/sdk/__init__.py +107 -0
  253. tnfr/sdk/__init__.pyi +19 -0
  254. tnfr/sdk/adaptive_system.py +173 -0
  255. tnfr/sdk/adaptive_system.pyi +21 -0
  256. tnfr/sdk/builders.py +370 -0
  257. tnfr/sdk/builders.pyi +51 -0
  258. tnfr/sdk/fluent.py +1121 -0
  259. tnfr/sdk/fluent.pyi +74 -0
  260. tnfr/sdk/templates.py +342 -0
  261. tnfr/sdk/templates.pyi +41 -0
  262. tnfr/sdk/utils.py +341 -0
  263. tnfr/secure_config.py +46 -0
  264. tnfr/security/__init__.py +70 -0
  265. tnfr/security/database.py +514 -0
  266. tnfr/security/subprocess.py +503 -0
  267. tnfr/security/validation.py +290 -0
  268. tnfr/selector.py +247 -0
  269. tnfr/selector.pyi +19 -0
  270. tnfr/sense.py +378 -0
  271. tnfr/sense.pyi +23 -0
  272. tnfr/services/__init__.py +17 -0
  273. tnfr/services/orchestrator.py +325 -0
  274. tnfr/sparse/__init__.py +39 -0
  275. tnfr/sparse/representations.py +492 -0
  276. tnfr/structural.py +705 -0
  277. tnfr/structural.pyi +83 -0
  278. tnfr/telemetry/__init__.py +35 -0
  279. tnfr/telemetry/cache_metrics.py +226 -0
  280. tnfr/telemetry/cache_metrics.pyi +64 -0
  281. tnfr/telemetry/nu_f.py +422 -0
  282. tnfr/telemetry/nu_f.pyi +108 -0
  283. tnfr/telemetry/verbosity.py +36 -0
  284. tnfr/telemetry/verbosity.pyi +15 -0
  285. tnfr/tokens.py +58 -0
  286. tnfr/tokens.pyi +36 -0
  287. tnfr/tools/__init__.py +20 -0
  288. tnfr/tools/domain_templates.py +478 -0
  289. tnfr/tools/sequence_generator.py +846 -0
  290. tnfr/topology/__init__.py +13 -0
  291. tnfr/topology/asymmetry.py +151 -0
  292. tnfr/trace.py +543 -0
  293. tnfr/trace.pyi +42 -0
  294. tnfr/tutorials/__init__.py +38 -0
  295. tnfr/tutorials/autonomous_evolution.py +285 -0
  296. tnfr/tutorials/interactive.py +1576 -0
  297. tnfr/tutorials/structural_metabolism.py +238 -0
  298. tnfr/types.py +775 -0
  299. tnfr/types.pyi +357 -0
  300. tnfr/units.py +68 -0
  301. tnfr/units.pyi +13 -0
  302. tnfr/utils/__init__.py +282 -0
  303. tnfr/utils/__init__.pyi +215 -0
  304. tnfr/utils/cache.py +4223 -0
  305. tnfr/utils/cache.pyi +470 -0
  306. tnfr/utils/callbacks.py +375 -0
  307. tnfr/utils/callbacks.pyi +49 -0
  308. tnfr/utils/chunks.py +108 -0
  309. tnfr/utils/chunks.pyi +22 -0
  310. tnfr/utils/data.py +428 -0
  311. tnfr/utils/data.pyi +74 -0
  312. tnfr/utils/graph.py +85 -0
  313. tnfr/utils/graph.pyi +10 -0
  314. tnfr/utils/init.py +821 -0
  315. tnfr/utils/init.pyi +80 -0
  316. tnfr/utils/io.py +559 -0
  317. tnfr/utils/io.pyi +66 -0
  318. tnfr/utils/numeric.py +114 -0
  319. tnfr/utils/numeric.pyi +21 -0
  320. tnfr/validation/__init__.py +257 -0
  321. tnfr/validation/__init__.pyi +85 -0
  322. tnfr/validation/compatibility.py +460 -0
  323. tnfr/validation/compatibility.pyi +6 -0
  324. tnfr/validation/config.py +73 -0
  325. tnfr/validation/graph.py +139 -0
  326. tnfr/validation/graph.pyi +18 -0
  327. tnfr/validation/input_validation.py +755 -0
  328. tnfr/validation/invariants.py +712 -0
  329. tnfr/validation/rules.py +253 -0
  330. tnfr/validation/rules.pyi +44 -0
  331. tnfr/validation/runtime.py +279 -0
  332. tnfr/validation/runtime.pyi +28 -0
  333. tnfr/validation/sequence_validator.py +162 -0
  334. tnfr/validation/soft_filters.py +170 -0
  335. tnfr/validation/soft_filters.pyi +32 -0
  336. tnfr/validation/spectral.py +164 -0
  337. tnfr/validation/spectral.pyi +42 -0
  338. tnfr/validation/validator.py +1266 -0
  339. tnfr/validation/window.py +39 -0
  340. tnfr/validation/window.pyi +1 -0
  341. tnfr/visualization/__init__.py +98 -0
  342. tnfr/visualization/cascade_viz.py +256 -0
  343. tnfr/visualization/hierarchy.py +284 -0
  344. tnfr/visualization/sequence_plotter.py +784 -0
  345. tnfr/viz/__init__.py +60 -0
  346. tnfr/viz/matplotlib.py +278 -0
  347. tnfr/viz/matplotlib.pyi +35 -0
  348. tnfr-8.5.0.dist-info/METADATA +573 -0
  349. tnfr-8.5.0.dist-info/RECORD +353 -0
  350. tnfr-8.5.0.dist-info/entry_points.txt +3 -0
  351. tnfr-3.0.3.dist-info/licenses/LICENSE.txt → tnfr-8.5.0.dist-info/licenses/LICENSE.md +1 -1
  352. tnfr/constants.py +0 -183
  353. tnfr/dynamics.py +0 -543
  354. tnfr/helpers.py +0 -198
  355. tnfr/main.py +0 -37
  356. tnfr/operators.py +0 -296
  357. tnfr-3.0.3.dist-info/METADATA +0 -35
  358. tnfr-3.0.3.dist-info/RECORD +0 -13
  359. {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
  360. {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
tnfr/utils/numeric.py ADDED
@@ -0,0 +1,114 @@
1
+ """Numeric helper functions and compensated summation utilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from collections.abc import Iterable, Sequence
7
+ from typing import Any
8
+
9
+ __all__ = (
10
+ "clamp",
11
+ "clamp01",
12
+ "within_range",
13
+ "similarity_abs",
14
+ "kahan_sum_nd",
15
+ "angle_diff",
16
+ "angle_diff_array",
17
+ )
18
+
19
+
20
+ def clamp(x: float, a: float, b: float) -> float:
21
+ """Return ``x`` clamped to the ``[a, b]`` interval."""
22
+
23
+ return max(a, min(b, x))
24
+
25
+
26
+ def clamp01(x: float) -> float:
27
+ """Clamp ``x`` to the ``[0,1]`` interval."""
28
+
29
+ return clamp(float(x), 0.0, 1.0)
30
+
31
+
32
+ def within_range(val: float, lower: float, upper: float, tol: float = 1e-9) -> bool:
33
+ """Return ``True`` if ``val`` lies in ``[lower, upper]`` within ``tol``."""
34
+
35
+ v = float(val)
36
+ return lower <= v <= upper or abs(v - lower) <= tol or abs(v - upper) <= tol
37
+
38
+
39
+ def _norm01(x: float, lo: float, hi: float) -> float:
40
+ """Normalize ``x`` to the unit interval given bounds."""
41
+
42
+ if hi <= lo:
43
+ return 0.0
44
+ return clamp01((float(x) - float(lo)) / (float(hi) - float(lo)))
45
+
46
+
47
+ def similarity_abs(a: float, b: float, lo: float, hi: float) -> float:
48
+ """Return absolute similarity of ``a`` and ``b`` over ``[lo, hi]``."""
49
+
50
+ return 1.0 - _norm01(abs(float(a) - float(b)), 0.0, hi - lo)
51
+
52
+
53
+ def kahan_sum_nd(values: Iterable[Sequence[float]], dims: int) -> tuple[float, ...]:
54
+ """Return compensated sums of ``values`` with ``dims`` components."""
55
+
56
+ if dims < 1:
57
+ raise ValueError("dims must be >= 1")
58
+ totals = [0.0] * dims
59
+ comps = [0.0] * dims
60
+ for vs in values:
61
+ for i in range(dims):
62
+ v = vs[i]
63
+ t = totals[i] + v
64
+ if abs(totals[i]) >= abs(v):
65
+ comps[i] += (totals[i] - t) + v
66
+ else:
67
+ comps[i] += (v - t) + totals[i]
68
+ totals[i] = t
69
+ return tuple(float(totals[i] + comps[i]) for i in range(dims))
70
+
71
+
72
+ def angle_diff(a: float, b: float) -> float:
73
+ """Return the minimal difference between two angles in radians."""
74
+
75
+ return (float(a) - float(b) + math.pi) % math.tau - math.pi
76
+
77
+
78
+ def angle_diff_array(
79
+ a: Sequence[float] | "np.ndarray", # noqa: F821
80
+ b: Sequence[float] | "np.ndarray", # noqa: F821
81
+ *,
82
+ np: Any,
83
+ out: "np.ndarray | None" = None, # noqa: F821
84
+ where: "np.ndarray | None" = None, # noqa: F821
85
+ ) -> "np.ndarray": # noqa: F821
86
+ """Vectorised :func:`angle_diff` compatible with NumPy arrays."""
87
+
88
+ if np is None:
89
+ raise TypeError("angle_diff_array requires a NumPy module")
90
+
91
+ kwargs = {"where": where} if where is not None else {}
92
+ minuend = np.asarray(a, dtype=float)
93
+ subtrahend = np.asarray(b, dtype=float)
94
+ if out is None:
95
+ out = np.empty_like(minuend, dtype=float)
96
+ if where is not None:
97
+ out.fill(0.0)
98
+ else:
99
+ if getattr(out, "shape", None) != minuend.shape:
100
+ raise ValueError("out must match the broadcasted shape of inputs")
101
+
102
+ np.subtract(minuend, subtrahend, out=out, **kwargs)
103
+ np.add(out, math.pi, out=out, **kwargs)
104
+ if where is not None:
105
+ mask = np.asarray(where, dtype=bool)
106
+ if mask.shape != out.shape:
107
+ raise ValueError("where mask must match the broadcasted shape of inputs")
108
+ selected = out[mask]
109
+ if selected.size:
110
+ out[mask] = np.remainder(selected, math.tau)
111
+ else:
112
+ np.remainder(out, math.tau, out=out)
113
+ np.subtract(out, math.pi, out=out, **kwargs)
114
+ return out
tnfr/utils/numeric.pyi ADDED
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterable, Sequence
4
+ from typing import Any
5
+
6
+ __all__: tuple[str, ...]
7
+
8
+ def clamp(x: float, a: float, b: float) -> float: ...
9
+ def clamp01(x: float) -> float: ...
10
+ def within_range(val: float, lower: float, upper: float, tol: float = ...) -> bool: ...
11
+ def similarity_abs(a: float, b: float, lo: float, hi: float) -> float: ...
12
+ def kahan_sum_nd(values: Iterable[Sequence[float]], dims: int) -> tuple[float, ...]: ...
13
+ def angle_diff(a: float, b: float) -> float: ...
14
+ def angle_diff_array(
15
+ a: Sequence[float] | Any,
16
+ b: Sequence[float] | Any,
17
+ *,
18
+ np: Any,
19
+ out: Any | None = ...,
20
+ where: Any | None = ...,
21
+ ) -> Any: ...
@@ -0,0 +1,257 @@
1
+ """Unified validation interface consolidating grammar, graph and spectral checks.
2
+
3
+ RECOMMENDED: Use TNFRValidator for unified validation pipeline
4
+ ==============================================================
5
+
6
+ The TNFRValidator class provides a single entry point for all TNFR validation
7
+ operations, consolidating input validation, graph validation, invariant checking,
8
+ operator preconditions, and runtime validation into one coherent API.
9
+
10
+ Example Usage::
11
+
12
+ from tnfr.validation import TNFRValidator
13
+
14
+ validator = TNFRValidator()
15
+
16
+ # Comprehensive validation in one call
17
+ result = validator.validate(
18
+ graph=G,
19
+ epi=0.5,
20
+ vf=1.0,
21
+ include_invariants=True,
22
+ )
23
+
24
+ if not result['passed']:
25
+ print(f"Validation failed: {result['errors']}")
26
+
27
+ For detailed migration guide, see UNIFIED_VALIDATION_PIPELINE.md
28
+
29
+ Legacy API
30
+ ==========
31
+
32
+ This package also re-exports individual validation functions for backward
33
+ compatibility, but these may be deprecated in future versions. New code should
34
+ use TNFRValidator instead.
35
+ """
36
+
37
+ from __future__ import annotations
38
+
39
+ from ..compat.dataclass import dataclass
40
+ from typing import Any, Generic, Mapping, Protocol, TypeVar, runtime_checkable
41
+
42
+ SubjectT = TypeVar("SubjectT")
43
+
44
+
45
+ @dataclass(slots=True)
46
+ class ValidationOutcome(Generic[SubjectT]):
47
+ """Result emitted by all canonical TNFR validators."""
48
+
49
+ subject: SubjectT
50
+ """The validated subject in canonical form."""
51
+
52
+ passed: bool
53
+ """Whether the validation succeeded without invariant violations."""
54
+
55
+ summary: Mapping[str, Any]
56
+ """Structured diagnostics describing the performed checks."""
57
+
58
+ artifacts: Mapping[str, Any] | None = None
59
+ """Optional artefacts (e.g. clamped nodes, normalised vectors)."""
60
+
61
+
62
+ @runtime_checkable
63
+ class Validator(Protocol[SubjectT]):
64
+ """Contract implemented by runtime and spectral validators."""
65
+
66
+ def validate(
67
+ self, subject: SubjectT, /, **kwargs: Any
68
+ ) -> ValidationOutcome[SubjectT]:
69
+ """Validate ``subject`` returning a :class:`ValidationOutcome`."""
70
+
71
+ def report(self, outcome: "ValidationOutcome[SubjectT]") -> str:
72
+ """Produce a concise textual explanation for ``outcome``."""
73
+
74
+
75
+ # NOTE: Compatibility module deprecated - grammar emerges from TNFR structural dynamics
76
+ # Legacy exports kept for backward compatibility but will be removed in future versions
77
+ try:
78
+ from .compatibility import ( # noqa: F401
79
+ CANON_COMPAT,
80
+ CANON_FALLBACK,
81
+ CompatibilityLevel,
82
+ GRADUATED_COMPATIBILITY,
83
+ get_compatibility_level,
84
+ )
85
+
86
+ _COMPAT_AVAILABLE = True
87
+ except ImportError:
88
+ # Compatibility module removed - provide stubs for backward compatibility
89
+ _COMPAT_AVAILABLE = False
90
+ CANON_COMPAT = {}
91
+ CANON_FALLBACK = {}
92
+
93
+ class CompatibilityLevel:
94
+ EXCELLENT = "excellent"
95
+ GOOD = "good"
96
+ CAUTION = "caution"
97
+ AVOID = "avoid"
98
+
99
+ GRADUATED_COMPATIBILITY = {}
100
+
101
+ def get_compatibility_level(prev: str, next_op: str) -> str:
102
+ """Deprecated: Use frequency transition validation instead."""
103
+ import warnings
104
+
105
+ warnings.warn(
106
+ "get_compatibility_level is deprecated. "
107
+ "Grammar rules now emerge naturally from TNFR structural dynamics. "
108
+ "Use validate_frequency_transition from tnfr.operators.grammar instead.",
109
+ DeprecationWarning,
110
+ stacklevel=2,
111
+ )
112
+ return "good"
113
+
114
+
115
+ from ..operators import grammar as _grammar
116
+ from ..types import Glyph
117
+ from .graph import GRAPH_VALIDATORS, run_validators # noqa: F401
118
+ from .window import validate_window # noqa: F401
119
+ from .runtime import (
120
+ GraphCanonicalValidator,
121
+ apply_canonical_clamps,
122
+ validate_canon,
123
+ ) # noqa: F401
124
+ from .rules import coerce_glyph, get_norm, glyph_fallback, normalized_dnfr # noqa: F401
125
+ from .soft_filters import ( # noqa: F401
126
+ acceleration_norm,
127
+ check_repeats,
128
+ maybe_force,
129
+ soft_grammar_filters,
130
+ )
131
+ from .input_validation import ( # noqa: F401
132
+ ValidationError,
133
+ validate_epi_value,
134
+ validate_vf_value,
135
+ validate_theta_value,
136
+ validate_dnfr_value,
137
+ validate_node_id,
138
+ validate_glyph,
139
+ validate_tnfr_graph,
140
+ validate_glyph_factors,
141
+ validate_operator_parameters,
142
+ )
143
+ from .invariants import ( # noqa: F401
144
+ InvariantSeverity,
145
+ InvariantViolation,
146
+ TNFRInvariant,
147
+ Invariant1_EPIOnlyThroughOperators,
148
+ Invariant2_VfInHzStr,
149
+ Invariant3_DNFRSemantics,
150
+ Invariant4_OperatorClosure,
151
+ Invariant5_ExplicitPhaseChecks,
152
+ Invariant6_NodeBirthCollapse,
153
+ Invariant7_OperationalFractality,
154
+ Invariant8_ControlledDeterminism,
155
+ Invariant9_StructuralMetrics,
156
+ Invariant10_DomainNeutrality,
157
+ )
158
+ from .validator import ( # noqa: F401
159
+ TNFRValidator,
160
+ TNFRValidationError,
161
+ )
162
+ from .sequence_validator import ( # noqa: F401
163
+ SequenceSemanticValidator,
164
+ )
165
+ from .config import ( # noqa: F401
166
+ ValidationConfig,
167
+ validation_config,
168
+ configure_validation,
169
+ )
170
+
171
+ _GRAMMAR_EXPORTS = tuple(getattr(_grammar, "__all__", ()))
172
+
173
+ globals().update({name: getattr(_grammar, name) for name in _GRAMMAR_EXPORTS})
174
+
175
+ _RUNTIME_EXPORTS = (
176
+ "ValidationOutcome",
177
+ "Validator",
178
+ "GraphCanonicalValidator",
179
+ "apply_canonical_clamps",
180
+ "validate_canon",
181
+ "GRAPH_VALIDATORS",
182
+ "run_validators",
183
+ "CANON_COMPAT",
184
+ "CANON_FALLBACK",
185
+ "validate_window",
186
+ "coerce_glyph",
187
+ "get_norm",
188
+ "glyph_fallback",
189
+ "normalized_dnfr",
190
+ "acceleration_norm",
191
+ "check_repeats",
192
+ "maybe_force",
193
+ "soft_grammar_filters",
194
+ "NFRValidator",
195
+ "ValidationError",
196
+ "validate_epi_value",
197
+ "validate_vf_value",
198
+ "validate_theta_value",
199
+ "validate_dnfr_value",
200
+ "validate_node_id",
201
+ "validate_glyph",
202
+ "validate_tnfr_graph",
203
+ "validate_glyph_factors",
204
+ "validate_operator_parameters",
205
+ "InvariantSeverity",
206
+ "InvariantViolation",
207
+ "TNFRInvariant",
208
+ "Invariant1_EPIOnlyThroughOperators",
209
+ "Invariant2_VfInHzStr",
210
+ "Invariant3_DNFRSemantics",
211
+ "Invariant4_OperatorClosure",
212
+ "Invariant5_ExplicitPhaseChecks",
213
+ "Invariant6_NodeBirthCollapse",
214
+ "Invariant7_OperationalFractality",
215
+ "Invariant8_ControlledDeterminism",
216
+ "Invariant9_StructuralMetrics",
217
+ "Invariant10_DomainNeutrality",
218
+ "TNFRValidator",
219
+ "TNFRValidationError",
220
+ "SequenceSemanticValidator",
221
+ "ValidationConfig",
222
+ "validation_config",
223
+ "configure_validation",
224
+ )
225
+
226
+ __all__ = _GRAMMAR_EXPORTS + _RUNTIME_EXPORTS
227
+
228
+ _ENFORCE_CANONICAL_GRAMMAR = _grammar.enforce_canonical_grammar
229
+
230
+
231
+ def enforce_canonical_grammar(
232
+ G: Any,
233
+ n: Any,
234
+ cand: Any,
235
+ ctx: Any | None = None,
236
+ ) -> Any:
237
+ """Proxy to the canonical grammar enforcement helper preserving Glyph outputs."""
238
+
239
+ result = _ENFORCE_CANONICAL_GRAMMAR(G, n, cand, ctx)
240
+ if isinstance(cand, Glyph) and not isinstance(result, Glyph):
241
+ translated = _grammar.function_name_to_glyph(result)
242
+ if translated is None and isinstance(result, str):
243
+ try:
244
+ translated = Glyph(result)
245
+ except (TypeError, ValueError):
246
+ translated = None
247
+ if translated is not None:
248
+ return translated
249
+ return result
250
+
251
+
252
+ def __getattr__(name: str) -> Any:
253
+ if name == "NFRValidator":
254
+ from .spectral import NFRValidator as _NFRValidator
255
+
256
+ return _NFRValidator
257
+ raise AttributeError(name)
@@ -0,0 +1,85 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Mapping
4
+ from typing import Any, Generic, Protocol, TypeVar
5
+
6
+ from ..types import Glyph, TNFRGraph
7
+ from .compatibility import (
8
+ CANON_COMPAT as CANON_COMPAT,
9
+ CANON_FALLBACK as CANON_FALLBACK,
10
+ )
11
+ from ..operators.grammar import (
12
+ GrammarContext,
13
+ MutationPreconditionError,
14
+ RepeatWindowError,
15
+ SequenceSyntaxError,
16
+ SequenceValidationResult,
17
+ StructuralGrammarError,
18
+ TholClosureError,
19
+ TransitionCompatibilityError,
20
+ apply_glyph_with_grammar,
21
+ enforce_canonical_grammar,
22
+ on_applied_glyph,
23
+ record_grammar_violation,
24
+ validate_sequence,
25
+ )
26
+ from .graph import GRAPH_VALIDATORS, run_validators
27
+ from .window import validate_window
28
+ from .rules import coerce_glyph, get_norm, glyph_fallback, normalized_dnfr
29
+ from .soft_filters import (
30
+ acceleration_norm,
31
+ check_repeats,
32
+ maybe_force,
33
+ soft_grammar_filters,
34
+ )
35
+ from .runtime import GraphCanonicalValidator, apply_canonical_clamps, validate_canon
36
+ from .spectral import NFRValidator
37
+
38
+ SubjectT = TypeVar("SubjectT")
39
+
40
+ class ValidationOutcome(Generic[SubjectT]):
41
+ subject: SubjectT
42
+ passed: bool
43
+ summary: Mapping[str, Any]
44
+ artifacts: Mapping[str, Any] | None
45
+
46
+ class Validator(Protocol[SubjectT]):
47
+ def validate(
48
+ self, subject: SubjectT, /, **kwargs: Any
49
+ ) -> ValidationOutcome[SubjectT]: ...
50
+ def report(self, outcome: ValidationOutcome[SubjectT]) -> str: ...
51
+
52
+ __all__ = (
53
+ "validate_sequence",
54
+ "GrammarContext",
55
+ "StructuralGrammarError",
56
+ "RepeatWindowError",
57
+ "MutationPreconditionError",
58
+ "TholClosureError",
59
+ "TransitionCompatibilityError",
60
+ "SequenceSyntaxError",
61
+ "SequenceValidationResult",
62
+ "apply_glyph_with_grammar",
63
+ "enforce_canonical_grammar",
64
+ "on_applied_glyph",
65
+ "record_grammar_violation",
66
+ "ValidationOutcome",
67
+ "Validator",
68
+ "GraphCanonicalValidator",
69
+ "apply_canonical_clamps",
70
+ "validate_canon",
71
+ "GRAPH_VALIDATORS",
72
+ "run_validators",
73
+ "CANON_COMPAT",
74
+ "CANON_FALLBACK",
75
+ "validate_window",
76
+ "coerce_glyph",
77
+ "get_norm",
78
+ "glyph_fallback",
79
+ "normalized_dnfr",
80
+ "acceleration_norm",
81
+ "check_repeats",
82
+ "maybe_force",
83
+ "soft_grammar_filters",
84
+ "NFRValidator",
85
+ )