tnfr 4.5.1__py3-none-any.whl → 6.0.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.
Files changed (170) hide show
  1. tnfr/__init__.py +270 -90
  2. tnfr/__init__.pyi +40 -0
  3. tnfr/_compat.py +11 -0
  4. tnfr/_version.py +7 -0
  5. tnfr/_version.pyi +7 -0
  6. tnfr/alias.py +631 -0
  7. tnfr/alias.pyi +140 -0
  8. tnfr/cache.py +732 -0
  9. tnfr/cache.pyi +232 -0
  10. tnfr/callback_utils.py +381 -0
  11. tnfr/callback_utils.pyi +105 -0
  12. tnfr/cli/__init__.py +89 -0
  13. tnfr/cli/__init__.pyi +47 -0
  14. tnfr/cli/arguments.py +199 -0
  15. tnfr/cli/arguments.pyi +33 -0
  16. tnfr/cli/execution.py +322 -0
  17. tnfr/cli/execution.pyi +80 -0
  18. tnfr/cli/utils.py +34 -0
  19. tnfr/cli/utils.pyi +8 -0
  20. tnfr/config/__init__.py +12 -0
  21. tnfr/config/__init__.pyi +8 -0
  22. tnfr/config/constants.py +104 -0
  23. tnfr/config/constants.pyi +12 -0
  24. tnfr/config/init.py +36 -0
  25. tnfr/config/init.pyi +8 -0
  26. tnfr/config/operator_names.py +106 -0
  27. tnfr/config/operator_names.pyi +28 -0
  28. tnfr/config/presets.py +104 -0
  29. tnfr/config/presets.pyi +7 -0
  30. tnfr/constants/__init__.py +228 -0
  31. tnfr/constants/__init__.pyi +104 -0
  32. tnfr/constants/core.py +158 -0
  33. tnfr/constants/core.pyi +17 -0
  34. tnfr/constants/init.py +31 -0
  35. tnfr/constants/init.pyi +12 -0
  36. tnfr/constants/metric.py +102 -0
  37. tnfr/constants/metric.pyi +19 -0
  38. tnfr/constants_glyphs.py +16 -0
  39. tnfr/constants_glyphs.pyi +12 -0
  40. tnfr/dynamics/__init__.py +136 -0
  41. tnfr/dynamics/__init__.pyi +83 -0
  42. tnfr/dynamics/adaptation.py +201 -0
  43. tnfr/dynamics/aliases.py +22 -0
  44. tnfr/dynamics/coordination.py +343 -0
  45. tnfr/dynamics/dnfr.py +2315 -0
  46. tnfr/dynamics/dnfr.pyi +33 -0
  47. tnfr/dynamics/integrators.py +561 -0
  48. tnfr/dynamics/integrators.pyi +35 -0
  49. tnfr/dynamics/runtime.py +521 -0
  50. tnfr/dynamics/sampling.py +34 -0
  51. tnfr/dynamics/sampling.pyi +7 -0
  52. tnfr/dynamics/selectors.py +680 -0
  53. tnfr/execution.py +216 -0
  54. tnfr/execution.pyi +65 -0
  55. tnfr/flatten.py +283 -0
  56. tnfr/flatten.pyi +28 -0
  57. tnfr/gamma.py +320 -89
  58. tnfr/gamma.pyi +40 -0
  59. tnfr/glyph_history.py +337 -0
  60. tnfr/glyph_history.pyi +53 -0
  61. tnfr/grammar.py +23 -153
  62. tnfr/grammar.pyi +13 -0
  63. tnfr/helpers/__init__.py +151 -0
  64. tnfr/helpers/__init__.pyi +66 -0
  65. tnfr/helpers/numeric.py +88 -0
  66. tnfr/helpers/numeric.pyi +12 -0
  67. tnfr/immutable.py +214 -0
  68. tnfr/immutable.pyi +37 -0
  69. tnfr/initialization.py +199 -0
  70. tnfr/initialization.pyi +73 -0
  71. tnfr/io.py +311 -0
  72. tnfr/io.pyi +11 -0
  73. tnfr/locking.py +37 -0
  74. tnfr/locking.pyi +7 -0
  75. tnfr/metrics/__init__.py +41 -0
  76. tnfr/metrics/__init__.pyi +20 -0
  77. tnfr/metrics/coherence.py +1469 -0
  78. tnfr/metrics/common.py +149 -0
  79. tnfr/metrics/common.pyi +15 -0
  80. tnfr/metrics/core.py +259 -0
  81. tnfr/metrics/core.pyi +13 -0
  82. tnfr/metrics/diagnosis.py +840 -0
  83. tnfr/metrics/diagnosis.pyi +89 -0
  84. tnfr/metrics/export.py +151 -0
  85. tnfr/metrics/glyph_timing.py +369 -0
  86. tnfr/metrics/reporting.py +152 -0
  87. tnfr/metrics/reporting.pyi +12 -0
  88. tnfr/metrics/sense_index.py +294 -0
  89. tnfr/metrics/sense_index.pyi +9 -0
  90. tnfr/metrics/trig.py +216 -0
  91. tnfr/metrics/trig.pyi +12 -0
  92. tnfr/metrics/trig_cache.py +105 -0
  93. tnfr/metrics/trig_cache.pyi +10 -0
  94. tnfr/node.py +255 -177
  95. tnfr/node.pyi +161 -0
  96. tnfr/observers.py +154 -150
  97. tnfr/observers.pyi +46 -0
  98. tnfr/ontosim.py +135 -134
  99. tnfr/ontosim.pyi +33 -0
  100. tnfr/operators/__init__.py +452 -0
  101. tnfr/operators/__init__.pyi +31 -0
  102. tnfr/operators/definitions.py +181 -0
  103. tnfr/operators/definitions.pyi +92 -0
  104. tnfr/operators/jitter.py +266 -0
  105. tnfr/operators/jitter.pyi +11 -0
  106. tnfr/operators/registry.py +80 -0
  107. tnfr/operators/registry.pyi +15 -0
  108. tnfr/operators/remesh.py +569 -0
  109. tnfr/presets.py +10 -23
  110. tnfr/presets.pyi +7 -0
  111. tnfr/py.typed +0 -0
  112. tnfr/rng.py +440 -0
  113. tnfr/rng.pyi +14 -0
  114. tnfr/selector.py +217 -0
  115. tnfr/selector.pyi +19 -0
  116. tnfr/sense.py +307 -142
  117. tnfr/sense.pyi +30 -0
  118. tnfr/structural.py +69 -164
  119. tnfr/structural.pyi +46 -0
  120. tnfr/telemetry/__init__.py +13 -0
  121. tnfr/telemetry/verbosity.py +37 -0
  122. tnfr/tokens.py +61 -0
  123. tnfr/tokens.pyi +41 -0
  124. tnfr/trace.py +520 -95
  125. tnfr/trace.pyi +68 -0
  126. tnfr/types.py +382 -17
  127. tnfr/types.pyi +145 -0
  128. tnfr/utils/__init__.py +158 -0
  129. tnfr/utils/__init__.pyi +133 -0
  130. tnfr/utils/cache.py +755 -0
  131. tnfr/utils/cache.pyi +156 -0
  132. tnfr/utils/data.py +267 -0
  133. tnfr/utils/data.pyi +73 -0
  134. tnfr/utils/graph.py +87 -0
  135. tnfr/utils/graph.pyi +10 -0
  136. tnfr/utils/init.py +746 -0
  137. tnfr/utils/init.pyi +85 -0
  138. tnfr/utils/io.py +157 -0
  139. tnfr/utils/io.pyi +10 -0
  140. tnfr/utils/validators.py +130 -0
  141. tnfr/utils/validators.pyi +19 -0
  142. tnfr/validation/__init__.py +25 -0
  143. tnfr/validation/__init__.pyi +17 -0
  144. tnfr/validation/compatibility.py +59 -0
  145. tnfr/validation/compatibility.pyi +8 -0
  146. tnfr/validation/grammar.py +149 -0
  147. tnfr/validation/grammar.pyi +11 -0
  148. tnfr/validation/rules.py +194 -0
  149. tnfr/validation/rules.pyi +18 -0
  150. tnfr/validation/syntax.py +151 -0
  151. tnfr/validation/syntax.pyi +7 -0
  152. tnfr-6.0.0.dist-info/METADATA +135 -0
  153. tnfr-6.0.0.dist-info/RECORD +157 -0
  154. tnfr/cli.py +0 -322
  155. tnfr/config.py +0 -41
  156. tnfr/constants.py +0 -277
  157. tnfr/dynamics.py +0 -814
  158. tnfr/helpers.py +0 -264
  159. tnfr/main.py +0 -47
  160. tnfr/metrics.py +0 -597
  161. tnfr/operators.py +0 -525
  162. tnfr/program.py +0 -176
  163. tnfr/scenarios.py +0 -34
  164. tnfr/validators.py +0 -38
  165. tnfr-4.5.1.dist-info/METADATA +0 -221
  166. tnfr-4.5.1.dist-info/RECORD +0 -28
  167. {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/WHEEL +0 -0
  168. {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/entry_points.txt +0 -0
  169. {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/licenses/LICENSE.md +0 -0
  170. {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,194 @@
1
+ """Validation helpers grouped by rule type.
2
+
3
+ These utilities implement the canonical checks required by
4
+ :mod:`tnfr.validation.grammar`. They are organised here to make it
5
+ explicit which pieces enforce repetition control, transition
6
+ compatibility or stabilisation thresholds.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Any, Callable, Mapping, TYPE_CHECKING
12
+
13
+ from ..alias import get_attr
14
+ from ..constants import get_aliases
15
+ from ..glyph_history import recent_glyph
16
+ from ..helpers.numeric import clamp01
17
+ from ..metrics.common import normalize_dnfr
18
+ from ..types import Glyph
19
+ from .compatibility import CANON_COMPAT, CANON_FALLBACK
20
+
21
+ if TYPE_CHECKING: # pragma: no cover - only for typing
22
+ from .grammar import GrammarContext
23
+
24
+ ALIAS_SI = get_aliases("SI")
25
+ ALIAS_D2EPI = get_aliases("D2EPI")
26
+
27
+ __all__ = [
28
+ "coerce_glyph",
29
+ "glyph_fallback",
30
+ "get_norm",
31
+ "normalized_dnfr",
32
+ "_norm_attr",
33
+ "_si",
34
+ "_accel_norm",
35
+ "_check_repeats",
36
+ "_maybe_force",
37
+ "_check_oz_to_zhir",
38
+ "_check_thol_closure",
39
+ "_check_compatibility",
40
+ ]
41
+
42
+
43
+ def coerce_glyph(val: Any) -> Glyph | Any:
44
+ """Return ``val`` coerced to :class:`Glyph` when possible."""
45
+
46
+ try:
47
+ return Glyph(val)
48
+ except (ValueError, TypeError):
49
+ return val
50
+
51
+
52
+ def glyph_fallback(cand_key: str, fallbacks: Mapping[str, Any]) -> Glyph | str:
53
+ """Determine fallback glyph for ``cand_key`` considering canon tables."""
54
+
55
+ glyph_key = coerce_glyph(cand_key)
56
+ canon_fb = (
57
+ CANON_FALLBACK.get(glyph_key, cand_key)
58
+ if isinstance(glyph_key, Glyph)
59
+ else cand_key
60
+ )
61
+ fb = fallbacks.get(cand_key, canon_fb)
62
+ return coerce_glyph(fb)
63
+
64
+
65
+ # -------------------------
66
+ # Normalisation helpers
67
+ # -------------------------
68
+
69
+ def get_norm(ctx: "GrammarContext", key: str) -> float:
70
+ """Retrieve a global normalisation value from ``ctx.norms``."""
71
+
72
+ return float(ctx.norms.get(key, 1.0)) or 1.0
73
+
74
+
75
+ def _norm_attr(ctx: "GrammarContext", nd, attr_alias: str, norm_key: str) -> float:
76
+ """Normalise ``attr_alias`` using the global maximum ``norm_key``."""
77
+
78
+ max_val = get_norm(ctx, norm_key)
79
+ return clamp01(abs(get_attr(nd, attr_alias, 0.0)) / max_val)
80
+
81
+
82
+ def _si(nd) -> float:
83
+ """Return the structural sense index for ``nd`` clamped to ``[0, 1]``."""
84
+
85
+ return clamp01(get_attr(nd, ALIAS_SI, 0.5))
86
+
87
+
88
+ def _accel_norm(ctx: "GrammarContext", nd) -> float:
89
+ """Normalise acceleration using the global maximum."""
90
+
91
+ return _norm_attr(ctx, nd, ALIAS_D2EPI, "accel_max")
92
+
93
+
94
+ def normalized_dnfr(ctx: "GrammarContext", nd) -> float:
95
+ """Normalise |ΔNFR| using the configured global maximum."""
96
+
97
+ return normalize_dnfr(nd, get_norm(ctx, "dnfr_max"))
98
+
99
+
100
+ # -------------------------
101
+ # Validation rules
102
+ # -------------------------
103
+
104
+ def _check_repeats(ctx: "GrammarContext", n, cand: Glyph | str) -> Glyph | str:
105
+ """Avoid recent repetitions according to ``ctx.cfg_soft``."""
106
+
107
+ nd = ctx.G.nodes[n]
108
+ cfg = ctx.cfg_soft
109
+ gwin = int(cfg.get("window", 0))
110
+ avoid = set(cfg.get("avoid_repeats", []))
111
+ fallbacks = cfg.get("fallbacks", {})
112
+ cand_key = cand.value if isinstance(cand, Glyph) else str(cand)
113
+ if gwin > 0 and cand_key in avoid and recent_glyph(nd, cand_key, gwin):
114
+ return glyph_fallback(cand_key, fallbacks)
115
+ return cand
116
+
117
+
118
+ def _maybe_force(
119
+ ctx: "GrammarContext",
120
+ n,
121
+ cand: Glyph | str,
122
+ original: Glyph | str,
123
+ accessor: Callable[["GrammarContext", dict[str, Any]], float],
124
+ key: str,
125
+ ) -> Glyph | str:
126
+ """Restore ``original`` if ``accessor`` exceeds ``key`` threshold."""
127
+
128
+ if cand == original:
129
+ return cand
130
+ force_th = float(ctx.cfg_soft.get(key, 0.60))
131
+ if accessor(ctx, ctx.G.nodes[n]) >= force_th:
132
+ return original
133
+ return cand
134
+
135
+
136
+ def _check_oz_to_zhir(ctx: "GrammarContext", n, cand: Glyph | str) -> Glyph | str:
137
+ """Enforce OZ precedents before allowing ZHIR mutations."""
138
+
139
+ nd = ctx.G.nodes[n]
140
+ cand_glyph = coerce_glyph(cand)
141
+ if cand_glyph == Glyph.ZHIR:
142
+ cfg = ctx.cfg_canon
143
+ win = int(cfg.get("zhir_requires_oz_window", 3))
144
+ dn_min = float(cfg.get("zhir_dnfr_min", 0.05))
145
+ if (
146
+ not recent_glyph(nd, Glyph.OZ, win)
147
+ and normalized_dnfr(ctx, nd) < dn_min
148
+ ):
149
+ return Glyph.OZ
150
+ return cand
151
+
152
+
153
+ def _check_thol_closure(
154
+ ctx: "GrammarContext", n, cand: Glyph | str, st: dict[str, Any]
155
+ ) -> Glyph | str:
156
+ """Close THOL blocks with canonical glyphs once stabilised."""
157
+
158
+ nd = ctx.G.nodes[n]
159
+ if st.get("thol_open", False):
160
+ st["thol_len"] = int(st.get("thol_len", 0)) + 1
161
+ cfg = ctx.cfg_canon
162
+ minlen = int(cfg.get("thol_min_len", 2))
163
+ maxlen = int(cfg.get("thol_max_len", 6))
164
+ close_dn = float(cfg.get("thol_close_dnfr", 0.15))
165
+ if st["thol_len"] >= maxlen or (
166
+ st["thol_len"] >= minlen
167
+ and normalized_dnfr(ctx, nd) <= close_dn
168
+ ):
169
+ return (
170
+ Glyph.NUL
171
+ if _si(nd) >= float(cfg.get("si_high", 0.66))
172
+ else Glyph.SHA
173
+ )
174
+ return cand
175
+
176
+
177
+ def _check_compatibility(ctx: "GrammarContext", n, cand: Glyph | str) -> Glyph | str:
178
+ """Verify canonical transition compatibility for ``cand``."""
179
+
180
+ nd = ctx.G.nodes[n]
181
+ hist = nd.get("glyph_history")
182
+ prev = hist[-1] if hist else None
183
+ prev_glyph = coerce_glyph(prev)
184
+ cand_glyph = coerce_glyph(cand)
185
+ if isinstance(prev_glyph, Glyph):
186
+ allowed = CANON_COMPAT.get(prev_glyph)
187
+ if allowed is None:
188
+ return cand
189
+ if isinstance(cand_glyph, Glyph):
190
+ if cand_glyph not in allowed:
191
+ return CANON_FALLBACK.get(prev_glyph, cand_glyph)
192
+ else:
193
+ return CANON_FALLBACK.get(prev_glyph, cand)
194
+ return cand
@@ -0,0 +1,18 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ _accel_norm: Any
8
+ _check_compatibility: Any
9
+ _check_oz_to_zhir: Any
10
+ _check_repeats: Any
11
+ _check_thol_closure: Any
12
+ _maybe_force: Any
13
+ _norm_attr: Any
14
+ _si: Any
15
+ coerce_glyph: Any
16
+ get_norm: Any
17
+ glyph_fallback: Any
18
+ normalized_dnfr: Any
@@ -0,0 +1,151 @@
1
+ """Syntax validation for TNFR operator sequences."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable
6
+
7
+ from ..operators.registry import OPERATORS
8
+ from ..config.operator_names import (
9
+ COHERENCE,
10
+ INTERMEDIATE_OPERATORS,
11
+ RECEPTION,
12
+ SELF_ORGANIZATION,
13
+ SELF_ORGANIZATION_CLOSURES,
14
+ VALID_END_OPERATORS,
15
+ VALID_START_OPERATORS,
16
+ canonical_operator_name,
17
+ operator_display_name,
18
+ )
19
+
20
+ __all__ = ("validate_sequence",)
21
+
22
+
23
+ _MISSING = object()
24
+
25
+
26
+ _CANONICAL_START = tuple(sorted(VALID_START_OPERATORS))
27
+ _CANONICAL_INTERMEDIATE = tuple(sorted(INTERMEDIATE_OPERATORS))
28
+ _CANONICAL_END = tuple(sorted(VALID_END_OPERATORS))
29
+
30
+
31
+ def _format_token_group(tokens: tuple[str, ...]) -> str:
32
+ return ", ".join(operator_display_name(token) for token in sorted(tokens))
33
+
34
+
35
+ def _validate_start(token: str) -> tuple[bool, str]:
36
+ """Ensure the sequence begins with a valid structural operator."""
37
+
38
+ if not isinstance(token, str):
39
+ return False, "tokens must be str"
40
+ if token not in VALID_START_OPERATORS:
41
+ valid_tokens = _format_token_group(_CANONICAL_START)
42
+ return False, f"must start with {valid_tokens}"
43
+ return True, ""
44
+
45
+
46
+ def _validate_intermediate(
47
+ found_reception: bool, found_coherence: bool, seen_intermediate: bool
48
+ ) -> tuple[bool, str]:
49
+ """Check that the central TNFR segment is present."""
50
+
51
+ if not (found_reception and found_coherence):
52
+ return False, f"missing {RECEPTION}→{COHERENCE} segment"
53
+ if not seen_intermediate:
54
+ intermediate_tokens = _format_token_group(_CANONICAL_INTERMEDIATE)
55
+ return False, f"missing {intermediate_tokens} segment"
56
+ return True, ""
57
+
58
+
59
+ def _validate_end(last_token: str, open_thol: bool) -> tuple[bool, str]:
60
+ """Validate closing operator and any pending THOL blocks."""
61
+
62
+ if last_token not in VALID_END_OPERATORS:
63
+ cierre_tokens = _format_token_group(_CANONICAL_END)
64
+ return False, f"sequence must end with {cierre_tokens}"
65
+ if open_thol:
66
+ return False, "THOL block without closure"
67
+ return True, ""
68
+
69
+
70
+ def _validate_known_tokens(
71
+ token_to_canonical: dict[str, str]
72
+ ) -> tuple[bool, str]:
73
+ """Ensure all tokens map to canonical operators."""
74
+
75
+ unknown_tokens = {
76
+ alias
77
+ for alias, canonical in token_to_canonical.items()
78
+ if canonical not in OPERATORS
79
+ }
80
+ if unknown_tokens:
81
+ ordered = ", ".join(sorted(unknown_tokens))
82
+ return False, f"unknown tokens: {ordered}"
83
+ return True, ""
84
+
85
+
86
+ def _validate_token_sequence(names: list[str]) -> tuple[bool, str]:
87
+ """Validate token format and logical coherence in one pass."""
88
+
89
+ if not names:
90
+ return False, "empty sequence"
91
+
92
+ ok, msg = _validate_start(names[0])
93
+ if not ok:
94
+ return False, msg
95
+
96
+ token_to_canonical: dict[str, str] = {}
97
+ found_reception = False
98
+ found_coherence = False
99
+ seen_intermediate = False
100
+ open_thol = False
101
+
102
+ for name in names:
103
+ if not isinstance(name, str):
104
+ return False, "tokens must be str"
105
+ canonical = canonical_operator_name(name)
106
+ token_to_canonical[name] = canonical
107
+
108
+ if canonical == RECEPTION and not found_reception:
109
+ found_reception = True
110
+ elif found_reception and canonical == COHERENCE and not found_coherence:
111
+ found_coherence = True
112
+ elif (
113
+ found_coherence
114
+ and not seen_intermediate
115
+ and canonical in INTERMEDIATE_OPERATORS
116
+ ):
117
+ seen_intermediate = True
118
+
119
+ if canonical == SELF_ORGANIZATION:
120
+ open_thol = True
121
+ elif open_thol and canonical in SELF_ORGANIZATION_CLOSURES:
122
+ open_thol = False
123
+
124
+ ok, msg = _validate_known_tokens(token_to_canonical)
125
+ if not ok:
126
+ return False, msg
127
+ ok, msg = _validate_intermediate(found_reception, found_coherence, seen_intermediate)
128
+ if not ok:
129
+ return False, msg
130
+ ok, msg = _validate_end(names[-1], open_thol)
131
+ if not ok:
132
+ return False, msg
133
+ return True, "ok"
134
+
135
+
136
+ def validate_sequence(
137
+ names: Iterable[str] | object = _MISSING, **kwargs: object
138
+ ) -> tuple[bool, str]:
139
+ """Validate minimal TNFR syntax rules."""
140
+
141
+ if kwargs:
142
+ unexpected = ", ".join(sorted(kwargs))
143
+ raise TypeError(
144
+ f"validate_sequence() got unexpected keyword argument(s): {unexpected}"
145
+ )
146
+
147
+ if names is _MISSING:
148
+ raise TypeError("validate_sequence() missing required argument: 'names'")
149
+
150
+ sequence = list(names)
151
+ return _validate_token_sequence(sequence)
@@ -0,0 +1,7 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ validate_sequence: Any
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: tnfr
3
+ Version: 6.0.0
4
+ Summary: Modular structural-based dynamics on networks.
5
+ Author: fmg
6
+ License: MIT
7
+ Project-URL: Homepage, https://pypi.org/project/tnfr/
8
+ Project-URL: Repository, https://github.com/fermga/TNFR-Python-Engine
9
+ Project-URL: GPT, https://chatgpt.com/g/g-67abc78885a88191b2d67f94fd60dc97-tnfr-teoria-de-la-naturaleza-fractal-resonante
10
+ Keywords: TNFR,complex systems,fractals,resonance,networks,structural dynamics,structural analysis
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Intended Audience :: Science/Research
20
+ Classifier: Topic :: Scientific/Engineering
21
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
22
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE.md
26
+ Requires-Dist: networkx>=2.6
27
+ Requires-Dist: cachetools>=5
28
+ Requires-Dist: typing-extensions>=4.4; python_version < "3.10"
29
+ Provides-Extra: numpy
30
+ Requires-Dist: numpy>=1.24; extra == "numpy"
31
+ Provides-Extra: yaml
32
+ Requires-Dist: pyyaml>=6.0; extra == "yaml"
33
+ Provides-Extra: orjson
34
+ Requires-Dist: orjson>=3; extra == "orjson"
35
+ Provides-Extra: test
36
+ Requires-Dist: pytest>=7; extra == "test"
37
+ Requires-Dist: pytest-benchmark>=4; extra == "test"
38
+ Requires-Dist: pydocstyle>=6; extra == "test"
39
+ Requires-Dist: coverage>=7; extra == "test"
40
+ Requires-Dist: flake8>=5; extra == "test"
41
+ Requires-Dist: flake8-pyproject>=1.2; extra == "test"
42
+ Requires-Dist: vulture>=2; extra == "test"
43
+ Provides-Extra: typecheck
44
+ Requires-Dist: mypy>=1.8; extra == "typecheck"
45
+ Requires-Dist: networkx-stubs>=0.0.1; extra == "typecheck"
46
+ Requires-Dist: types-cachetools>=6.0.0.0; extra == "typecheck"
47
+ Requires-Dist: numpy>=1.24; extra == "typecheck"
48
+ Dynamic: license-file
49
+
50
+ # TNFR Python Engine
51
+
52
+ Canonical implementation of the Resonant Fractal Nature Theory (TNFR) for modelling structural
53
+ coherence. The engine seeds resonant nodes, applies structural operators, coordinates
54
+ ΔNFR/phase dynamics, and measures coherence metrics (C(t), Si, νf) without breaking the nodal
55
+ equation $\partial EPI/\partial t = \nu_f \cdot \Delta NFR(t)$.
56
+
57
+ ## Snapshot
58
+
59
+ - **Operate:** build nodes with `tnfr.create_nfr`, execute trajectories via
60
+ `tnfr.structural.run_sequence`, and evolve dynamics with `tnfr.dynamics.run`.
61
+ - **Observe:** register metrics/trace callbacks to capture ΔNFR, C(t), Si, and structural
62
+ histories
63
+ for every run.
64
+ - **Extend:** rely on the canonical operator grammar and invariants before introducing new
65
+ utilities or telemetry.
66
+
67
+ ## Quickstart
68
+
69
+ Install from PyPI (Python ≥ 3.9):
70
+
71
+ ```bash
72
+ pip install tnfr
73
+ ```
74
+
75
+ Then follow the [quickstart guide](docs/getting-started/quickstart.md) for Python and CLI
76
+ walkthroughs plus optional dependency caching helpers.
77
+
78
+ ## Documentation map
79
+
80
+ - [Documentation index](docs/index.md) — navigation hub for API chapters and examples.
81
+ - [API overview](docs/api/overview.md) — package map, invariants, and structural data flow.
82
+ - [Structural operators](docs/api/operators.md) — canonical grammar, key concepts, and typical
83
+ workflows.
84
+ - [Telemetry & utilities](docs/api/telemetry.md) — coherence metrics, trace capture, locking,
85
+ and helper facades.
86
+ - [Examples](docs/examples/README.md) — runnable scenarios, CLI artefacts, and token legend.
87
+
88
+ ## Documentation build workflow
89
+
90
+ Netlify publishes the documentation with [MkDocs](https://www.mkdocs.org/) so the generated
91
+ site preserves the canonical TNFR structure. The same steps can be executed locally:
92
+
93
+ 1. Create and activate a virtual environment (e.g. `python -m venv .venv && source .venv/bin/activate`).
94
+ 2. Install the documentation toolchain: `python -m pip install -r docs/requirements.txt`.
95
+ 3. Preview changes live with `mkdocs serve` or reproduce the Netlify pipeline with
96
+ `mkdocs build`, which writes the static site to the `site/` directory.
97
+
98
+ The Netlify build (`netlify.toml`) runs `python -m pip install -r docs/requirements.txt && mkdocs build`
99
+ and publishes the resulting `site/` directory, ensuring the hosted documentation matches local builds.
100
+
101
+ ## Local development
102
+
103
+ Use the helper scripts to keep formatting aligned with the canonical configuration and to reproduce
104
+ the quality gate locally:
105
+
106
+ ```bash
107
+ ./scripts/format.sh # Apply Black and isort across src/, tests/, scripts/, and benchmarks/
108
+ ./scripts/format.sh --check # Validate formatting without modifying files
109
+ ./scripts/run_tests.sh # Execute the full QA battery (type checks, tests, coverage, linting)
110
+ ```
111
+
112
+ The formatting helper automatically prefers `poetry run` when a Poetry environment is available and
113
+ falls back to `python -m` invocations so local runs mirror the tooling invoked in continuous
114
+ integration.
115
+
116
+ ## Additional resources
117
+
118
+ - [ARCHITECTURE.md](ARCHITECTURE.md) — orchestration layers and invariant enforcement.
119
+ - [CONTRIBUTING.md](CONTRIBUTING.md) — QA battery (`scripts/run_tests.sh`) and review
120
+ expectations.
121
+ - [TNFR.pdf](TNFR.pdf) — theoretical background, structural operators, and paradigm glossary.
122
+
123
+ ## Migration notes
124
+
125
+ - **Si dispersion keys:** Replace any remaining ``dSi_ddisp_fase`` entries in graph payloads
126
+ or configuration files with the English ``dSi_dphase_disp`` key before upgrading. The
127
+ runtime now raises :class:`ValueError` listing any unexpected sensitivity keys, and
128
+ :func:`tnfr.metrics.sense_index.compute_Si_node` rejects unknown keyword arguments.
129
+ - Refer to the [release notes](docs/releases.md#1100-si-dispersion-legacy-keys-removed) for
130
+ a migration snippet that rewrites stored graphs in place prior to running the new version.
131
+
132
+ ## Licensing
133
+
134
+ Released under the [MIT License](LICENSE.md). Cite the TNFR paradigm when publishing research
135
+ or derived artefacts based on this engine.
@@ -0,0 +1,157 @@
1
+ tnfr/__init__.py,sha256=zgPWxn__aqj45uTXna_lzywQ-5-TuxBYYt-BkMLXPiY,8679
2
+ tnfr/__init__.pyi,sha256=SVeCTtSpwlP-gtTzhX8OINlfFFuO43pyWunsc2I021Y,978
3
+ tnfr/_compat.py,sha256=VuXrIrkfwCGk_KJjgubhh3JE3S49Q6zoNaKgMVgpXFE,414
4
+ tnfr/_version.py,sha256=QBM2cy3Ta0_p9NQaMtYXdirM5XzS5wVntliMx9BDMgM,125
5
+ tnfr/_version.pyi,sha256=DbyhsjJTujojo0nxFtOdH94bxGxzReRJNjZoHV-zG1s,95
6
+ tnfr/alias.py,sha256=WfddprBly1jwWz10ozYErCi5I2ONAXjf2dwpOBxyqF8,18127
7
+ tnfr/alias.pyi,sha256=x4sS9Rt_M-pzQF_tJitR-HRxoyKNrn1s1lIj8zcV9us,2926
8
+ tnfr/cache.py,sha256=D5EZ1yDBQoXYcGH89wsdlnaojU3eH-MUACX8VDXWhFI,24442
9
+ tnfr/cache.pyi,sha256=MIH_3rs5OE1xt2VYOziShL0hGRctHFx2i7PThT-X3qw,5872
10
+ tnfr/callback_utils.py,sha256=YjGq7viVC95wFpSBJIt2fFDCp7OUWwpv5FpiWsTuzYA,12181
11
+ tnfr/callback_utils.pyi,sha256=Osu0xb9opdU7KeWC4MleelthiJHVqhZ4ia8UrRxOtvs,2365
12
+ tnfr/constants_glyphs.py,sha256=o0uTYkuLXaj3yM4CGAcnNcqwv9VC0I6x-hJzCPbzq9Q,401
13
+ tnfr/constants_glyphs.pyi,sha256=Xtm8NhTukF_rpn4Y7hy9O7aT1IcWSuQLcDpFcUnZnbk,192
14
+ tnfr/execution.py,sha256=md_Mzpe6M7VsQBt8_brKQPFfhnoRWftxi7YZC-LzmYM,5813
15
+ tnfr/execution.pyi,sha256=iPskC4i_jBPwNtvCXVr5tH71WD9mQCqAvKq7QjKDi2w,1465
16
+ tnfr/flatten.py,sha256=QbrZODPL0qTu9D7RVn3YGvq8QEq6f0GR60X-1kLho3c,8226
17
+ tnfr/flatten.pyi,sha256=dI7sVL2BTvFYvN6bWoQVtIKybOXZSogeko3pCvtp9Vo,594
18
+ tnfr/gamma.py,sha256=nkbBcP3H0gBZV_vABphsaY-Ick1i4gDj_X9PFnRoSQM,10998
19
+ tnfr/gamma.pyi,sha256=b2KKWTBGQ4fAMYIBUTumIFgS73xixk9ekd01cGNyFV4,1005
20
+ tnfr/glyph_history.py,sha256=ajLN0PIZWEQkaIaF8pJonseqAsem0utDZCD-UXirrWo,11527
21
+ tnfr/glyph_history.pyi,sha256=rRAu_jVFfkE7o7l1VE9-CSWXCnbfRs2BG_4WjYPQF_s,1397
22
+ tnfr/grammar.py,sha256=70lUuMqoB3GVomKD4rbQy_M5icBjp0-4XKwyAT6Z_gE,651
23
+ tnfr/grammar.pyi,sha256=UM6ntYDCQ3hEfYnV6e2O9K9G21VTkpx-YJYnX5j-2Lw,236
24
+ tnfr/immutable.py,sha256=SeNqRmbomKJjU6wC_ITe9gBGn9xEZjV1z67UQioSg7g,6445
25
+ tnfr/immutable.pyi,sha256=DHx-gRaygFPX2G5zfDQUjLsRB-tW5sZhhBRc16woD9I,1283
26
+ tnfr/initialization.py,sha256=ds8NfUEBku6pzIwWHNPOO8y1Gubio5dK6fYS80IHUJo,5914
27
+ tnfr/initialization.pyi,sha256=hDr2PMQmpye4xoA7m5Fgbpr-p2FLg3_LVSXu6D-apj0,1345
28
+ tnfr/io.py,sha256=U6eMQNSGa2wkHC7tsUrAq19UuPntoWiuCwd-br14qws,8316
29
+ tnfr/io.pyi,sha256=_x06jeSFJVJsyksACDnq9S-4l5X01YXlxn44y9ACXCA,181
30
+ tnfr/locking.py,sha256=mOvaENBNSsWw6KiBG_UXv4xXfZ9uQZvWw5SN2cKFmSU,1168
31
+ tnfr/locking.pyi,sha256=GoQ-C3l87O78jCi38VmUDpXwMnocPe0eavJFEN4QdXU,92
32
+ tnfr/node.py,sha256=qyEJ3ogOZoO9lAlCW3uyDhpRKqF7BinKrRy35ZywHGQ,7869
33
+ tnfr/node.pyi,sha256=uLAM1iu10BW3s8O7BwJcc1PWYE0v9YIQxVT1ZxYG2SE,3450
34
+ tnfr/observers.py,sha256=34OWK8YcE2m4UyqJeQMxpQBOv_KjSO4JG80F3nVziVI,5118
35
+ tnfr/observers.pyi,sha256=_mLFNOwrJAZb894noHW9Y94xBd4Dap3LHV8vx-L8oNk,881
36
+ tnfr/ontosim.py,sha256=Oqrgjib5J6igPi2sVbFJMLHKgw005lCVHPoZuboo08o,4035
37
+ tnfr/ontosim.pyi,sha256=__X4twVj8Y7uirGqx5UDlzMIYOBoU8ZqRBKOf836e6Q,565
38
+ tnfr/presets.py,sha256=FL2Fvi2mazD4PvaOxIosrQOnZ7KvNia-fiCf-4sF80U,312
39
+ tnfr/presets.pyi,sha256=8oHCzjv8AOcfWWRZb4pgTJ40HJUXbbrDOyQoSb_XsD8,94
40
+ tnfr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
+ tnfr/rng.py,sha256=BzrmsBXHdKsS1pt4u4J6VFA8AaH8Qh4yOjN_vjGMsYU,14122
42
+ tnfr/rng.pyi,sha256=95PakrXx9OYVrEUIrwR9xxuuGxiYK1ZZXWNm0cLf1AA,232
43
+ tnfr/selector.py,sha256=CuiMRNJ_isi_mRVfhWeyhrY1DfdOhn8VSXddArn1zhg,6164
44
+ tnfr/selector.pyi,sha256=LWwkUQloGu7SZFi4aedJA7snFd16oA9yaPYQP2tzvTY,379
45
+ tnfr/sense.py,sha256=ZUiaFJsP8wz5AkCywLxJN3dz1V9huFfnlE6m5InyvWQ,10148
46
+ tnfr/sense.pyi,sha256=9u-nqIEPaFp2GSrJF9AyNJEbhPnw-IjoIDM8QMc_R5I,794
47
+ tnfr/structural.py,sha256=_o8Kqaue3o7ohyozwbCO0taTEn4nLVNfE7P4F37KJDw,2526
48
+ tnfr/structural.pyi,sha256=WYLGl2quXH3iSnDZu0-ZKwsdGZLDpBtaWo0K3GOMQeY,847
49
+ tnfr/tokens.py,sha256=IOLowDN6JuiEVAnGcYtclpF_S9Orlu5BnEug5O3aERA,1214
50
+ tnfr/tokens.pyi,sha256=qo_cfFE3vybigYl6Bx6pstRwn0ay2Sdf91S5o8YWce0,683
51
+ tnfr/trace.py,sha256=y8bDQ4Rpb5DEr5qfnmZLcNty3pDKBhujYO7U8F5jrc8,15043
52
+ tnfr/trace.pyi,sha256=anufYVC1K-5UyoGcEk12f1BtGAwPG1bOUfT6XjQZxHk,1882
53
+ tnfr/types.py,sha256=t6jd_Wb3V1OuWUAx3ycmCbFje2Sshj6B8TOJNrv7MtI,11351
54
+ tnfr/types.pyi,sha256=VyfkdeGuwJP_3RXbVV4SozINJm7jr3XMEU9clJw6Mrw,4022
55
+ tnfr/cli/__init__.py,sha256=FTblTvNLe0v2QIrsMgiWwcD0_JoRkNOVsIwGlyk_4sE,2127
56
+ tnfr/cli/__init__.pyi,sha256=XYq749MAzQHqV9Lj7QHjN6I2qMTZTEP07w8S-odcNS0,1040
57
+ tnfr/cli/arguments.py,sha256=pklvrCn2AjD5gmCjfJpNs9UQLFGA2NziBh7HjVbkL80,6336
58
+ tnfr/cli/arguments.pyi,sha256=KzXFsqSohTnvvTAkMWBgRykWv2Fuc-lfIjbKyibY84s,1031
59
+ tnfr/cli/execution.py,sha256=jP8NMwKBDQZ-KvC0pVZStEnIUaSh-K_meIBiQSbW0Nk,9897
60
+ tnfr/cli/execution.pyi,sha256=IStpTub_NLFdMxMej3v15s7NPfIJB8hkL0pW_YuVdJc,2212
61
+ tnfr/cli/utils.py,sha256=aTsWm1b5QRZp4ZZStA1kqHiYT_wboqEpyTVNXVXnOoQ,977
62
+ tnfr/cli/utils.pyi,sha256=3ODz7i3t2cm9qjXfxzdLQgnfZHBdXTewEVsbwZdQGgs,105
63
+ tnfr/config/__init__.py,sha256=hcAneY0S8dH9kjHDBH7rlGbPH6r0F_WpkZ8J-5c4Q0M,384
64
+ tnfr/config/__init__.pyi,sha256=m1D1GQIyCbwnllwXNoPriPkxzBYIJUZBik-jJXdW_CA,113
65
+ tnfr/config/constants.py,sha256=8d_nXHpuM7DBKMeKonT0Wwft-oZgKxljYdhhZOOzceg,2830
66
+ tnfr/config/constants.pyi,sha256=Xtm8NhTukF_rpn4Y7hy9O7aT1IcWSuQLcDpFcUnZnbk,192
67
+ tnfr/config/init.py,sha256=srfCPDT8ddj2N2B7i9raHQeYKv3m2yswCKM67o7cfFQ,1029
68
+ tnfr/config/init.pyi,sha256=m1D1GQIyCbwnllwXNoPriPkxzBYIJUZBik-jJXdW_CA,113
69
+ tnfr/config/operator_names.py,sha256=iSefOgf-qniQI5OQhgH7auhVRveoX_0n3mkP11xHOdo,2705
70
+ tnfr/config/operator_names.pyi,sha256=9GgUMxZXzoemlnIjkTmtruOJ2DkA__DfjQTeouRNVu4,532
71
+ tnfr/config/presets.py,sha256=XHGkFAjBQ6t34xgMeL_9O-S2jPaXhEfgysEFhXcMlmQ,2481
72
+ tnfr/config/presets.pyi,sha256=8oHCzjv8AOcfWWRZb4pgTJ40HJUXbbrDOyQoSb_XsD8,94
73
+ tnfr/constants/__init__.py,sha256=2aMheGK04vELJARf47xHxkNZThQcSJPSoOV8kb3VqtE,6479
74
+ tnfr/constants/__init__.pyi,sha256=ukJKlu9VkWHKlcKlv_pyXHBKjE6HMqYckAO4pF6LqGc,2270
75
+ tnfr/constants/core.py,sha256=F7kVXaP_-nVhZIDq4327Z2Kxp2AI8yab8WGHDePIgTw,4718
76
+ tnfr/constants/core.pyi,sha256=H9oY3Skdse9qPSFw2gF7mpyAUzFCPwo3RaYIVnxDfvo,279
77
+ tnfr/constants/init.py,sha256=WdMKkdPKO7vyQoJAuoFnhWbb3n1nBkmkzprwyYj_ZN8,805
78
+ tnfr/constants/init.pyi,sha256=jdf_jVgcRlVxzFzioOw_ANXUbtAc-0iHfLLAT1tLyaw,169
79
+ tnfr/constants/metric.py,sha256=P7Zrw-4p7Nd7QwCVLRMV7GWop3LoeAdlm9NgAQnnbJU,3290
80
+ tnfr/constants/metric.pyi,sha256=x0U5uD9fzgmSUz_EoUdBE2zrEdbgnaMgbMxUFyA7vB8,280
81
+ tnfr/dynamics/__init__.py,sha256=OBfdBpz52CTv_nlhFc8arfnACwwoRr9O1iJpGITzi2E,3296
82
+ tnfr/dynamics/__init__.pyi,sha256=cRvvBpMV7G_5YF_mDJkvEcN1wTGBmdeEs-PJIihiZ1Q,1843
83
+ tnfr/dynamics/adaptation.py,sha256=WkmuLYY5wTvOJbeGKLfYAk2jYdP5caPVBPpib9fqTq8,7072
84
+ tnfr/dynamics/aliases.py,sha256=8SeUcsJRieXrvl7-oJiEcvLUke1AQSZnz4-djVJdeHg,445
85
+ tnfr/dynamics/coordination.py,sha256=VKlgqS7DA-2tWklwJUlD8DICJdiFGZX1gYMIElMeC_w,10814
86
+ tnfr/dynamics/dnfr.py,sha256=YXEpE-b5EWc1EFSBCneAf_GwK3JCUALw2JM3pGwmnzk,75723
87
+ tnfr/dynamics/dnfr.pyi,sha256=-hiGDoEEFtLb9Ggox1jhE_-ehkiaBL1kh7ClV-8913M,655
88
+ tnfr/dynamics/integrators.py,sha256=9zYrV4kr_s8L5CKPoXKwath0UIw_3r52jqce3jy95ks,16495
89
+ tnfr/dynamics/integrators.pyi,sha256=6bJaNKzZ5b1s5u4gktB1eACRH4oxVQNJTil-f1O02vI,843
90
+ tnfr/dynamics/runtime.py,sha256=ymP5BXZq5S7GtvfePUObMuMHMIhbUy6d6ZQbjcTYFU4,14762
91
+ tnfr/dynamics/sampling.py,sha256=FR2VAgcHc0eiUAK7YdAn6Ad1Vq2VtZTMceyOQzlqEno,1247
92
+ tnfr/dynamics/sampling.pyi,sha256=edfyDqgtvmK4w6zlBNG9nmGpZDVe3pdnNZYOLFbwIG8,102
93
+ tnfr/dynamics/selectors.py,sha256=a8M26H3K5ywJm4u5vTNt4yzrjR2FG5m-e6BMRE0v4YU,22447
94
+ tnfr/helpers/__init__.py,sha256=DrT3dtkR6oJ2-uv3XE_fbd7Pq69_tbyninrGMAtEAVQ,4042
95
+ tnfr/helpers/__init__.pyi,sha256=dae6lQfR-iXR1FJF9kSUKgqlzlH6dju7803AqsSbRco,1688
96
+ tnfr/helpers/numeric.py,sha256=ritFewhW1VNxCOHxBC71aNLSZUuJ23-MUsVn_IV7V8E,2693
97
+ tnfr/helpers/numeric.pyi,sha256=m6Tf_k9ZH2sro6z6g0wxariWSip6rVMct288zMDDcvo,174
98
+ tnfr/metrics/__init__.py,sha256=4gujlyn3aN95lkxCjQPPgKS_xJYm5ShcraeEkDYKR_E,885
99
+ tnfr/metrics/__init__.pyi,sha256=W5fUkKR9FeEcdHg4OVW2JPzxIRlQ71qtiYqoaEoAM3w,412
100
+ tnfr/metrics/coherence.py,sha256=BVzoJSLCt--eDaFTmTEYfRObZkRXjQgn_KzAcYcXQK0,46109
101
+ tnfr/metrics/common.py,sha256=R7jOzuxpenNkv-Y0iURMQOA9vtLTxr5Hdmna1OXohKA,4361
102
+ tnfr/metrics/common.pyi,sha256=QSOfl14yyDpQ0B6VvI3ecvpAH99mkrFXU35rJg_lXjU,289
103
+ tnfr/metrics/core.py,sha256=1L1shli3RxlGn4Y8xuYrsNfaE-9I3Qx7kHMXLwdfq7A,7208
104
+ tnfr/metrics/core.pyi,sha256=8s1j3oeTyzU5xyUIsuP_Q5DkXY6hja_j2xL7ghKcu-U,218
105
+ tnfr/metrics/diagnosis.py,sha256=P42FWqhOs955UB1cPm0rf1lFVB7wyz_0HLLoUFSeYII,26509
106
+ tnfr/metrics/diagnosis.pyi,sha256=I2PzErqAVEvYt8saFs8fF7ADFUXEwzPwiKuzRmR8XGs,2134
107
+ tnfr/metrics/export.py,sha256=F-gEES5RZopTRE45ISzYPRF_4ZF5HDa3qF_XNvurVE0,4735
108
+ tnfr/metrics/glyph_timing.py,sha256=0gdxDu-aMd6mlau_VCWpZxCxSZ6Iau53sCFDFpF7Wug,10851
109
+ tnfr/metrics/reporting.py,sha256=XcBwZl1-kwYLqxZELLR9oPsTVN--Z_thWqzVIANlVC4,4121
110
+ tnfr/metrics/reporting.pyi,sha256=uA7DP9bM7351dcq4qBooZDXJUSLXyWR3AE2_r9H29YI,194
111
+ tnfr/metrics/sense_index.py,sha256=qAUt1zbmSvvFGRusmQ5ssUaScuLCdNLnVO6BCS4hPNQ,9314
112
+ tnfr/metrics/sense_index.pyi,sha256=YK5rIvhGGN6KyZHVIirCrgBF3eDeJ2zPyfa7x19sqXM,135
113
+ tnfr/metrics/trig.py,sha256=Jyg9uwqNjSVRYFnYtyjrqnWSsFPKnrB6qcLof_tTD4Y,6548
114
+ tnfr/metrics/trig.pyi,sha256=nSssWGsGS7k4jvKWAYxICzoB13laM8PKTpPstWgIJNQ,249
115
+ tnfr/metrics/trig_cache.py,sha256=IPPIopGf5za8filSUGeymNHXEwfMZSRp0SNYgMdkHkc,3009
116
+ tnfr/metrics/trig_cache.pyi,sha256=wqxVFp27iiUBB9Uep8rEIU_MIh1PjtsaK_d2RpLGnfE,163
117
+ tnfr/operators/__init__.py,sha256=ea7doh9GgKIHpFOxkI4-ladMQcnIkWD1rvjurxx_ffA,13394
118
+ tnfr/operators/__init__.pyi,sha256=5xE25x2yK-o0JuqxbUmlP62dRXW4uWFDYcHfR5SifKg,588
119
+ tnfr/operators/definitions.py,sha256=4KG8BtIQ2sXKzyylqSoeJFnECdKVCujoVfFLHU4-iTY,3985
120
+ tnfr/operators/definitions.pyi,sha256=9Zj4-HjCy8kX3havevz5EPL5q3TtMuyabxfHRw95bak,1528
121
+ tnfr/operators/jitter.py,sha256=nO7gY2466UcKOYlpaVDEi4d5wvvNJRJWsbLU5xmcp0E,7833
122
+ tnfr/operators/jitter.pyi,sha256=FSrSKP51D5N7AdekOH9H-sVzBBaqnnmM2IQKfWlnQN0,188
123
+ tnfr/operators/registry.py,sha256=b7dO6n3gpUXgnYPhJhAQd0oElYNol43jkeQCP8iZn3U,2433
124
+ tnfr/operators/registry.pyi,sha256=CHuuHsvKsSo7mWSXMQJdJoXD0AHO6jrCjv8lVGuoEkY,314
125
+ tnfr/operators/remesh.py,sha256=VKqIucYJkQWUc1Ux0RlEpa8wOSjtN3u8MZWMt-0WdxQ,17869
126
+ tnfr/telemetry/__init__.py,sha256=Ugqk4Qiv4dIYTVpxGXdKnEBORDdmw19A7Ni2TBPsp7o,286
127
+ tnfr/telemetry/verbosity.py,sha256=6fN7IMhwtLKVQbch-PIN_vLxn3dw178SownD8-xlhKM,1048
128
+ tnfr/utils/__init__.py,sha256=UOUnzZVN-WGqyCHVGYiM9xkwwb83Mm4N6AqXySV_Da0,4375
129
+ tnfr/utils/__init__.pyi,sha256=EC12WoblgdRd4q_49XinqXklju2hyN9lvGUXbKRtCcw,2946
130
+ tnfr/utils/cache.py,sha256=brzDTG_cFBy8ENZs2je3GbFRgGKGl2t8bI8QsiIGd4c,22602
131
+ tnfr/utils/cache.pyi,sha256=sZnm7KKTvpM9CwI2y5v2G9L1NW3Gbo4MNMtC-_zZhOE,3782
132
+ tnfr/utils/data.py,sha256=nQFN0aWYHTX36UkniGXzBrqNYxCabBLVL2Rh99-y8ts,7805
133
+ tnfr/utils/data.pyi,sha256=O3Iy37c8KUE6kFozWTAU2FyaWuUGIrIM3sxdaBgpap4,1595
134
+ tnfr/utils/graph.py,sha256=wnkkAB-yS2KlGRWcwfLwdHjJLcenaa8S2xEzzsVHcRE,2780
135
+ tnfr/utils/graph.pyi,sha256=mrMVWDkJQhu8K3l2eUvOSgKCWlWij7e8pANzJjOFXKA,165
136
+ tnfr/utils/init.py,sha256=4tP7frGVtapI_TLWFW8k83AIzXL3FaGGjDPSmSrcJsU,22561
137
+ tnfr/utils/init.pyi,sha256=26t_q-CeJ5BDyXu80QsYojBknKlKQl7AoRTVgrbQNVw,2446
138
+ tnfr/utils/io.py,sha256=W3-aZ3axvLx0gmYR2zUmUvs9yMH2UPRIbp9Y-Z__rws,4730
139
+ tnfr/utils/io.pyi,sha256=l2_9a0mYrsnM4Frpi7jCxeueUD3-e6fYyKpZVya6ARY,168
140
+ tnfr/utils/validators.py,sha256=R0bvCZO0qXP1OqiVEKLMBX4P5nsy-tyuWKVf6mteg3E,3892
141
+ tnfr/utils/validators.pyi,sha256=6nPYp8N_vLAA8FNyQM_5iR41W8-OZS9oEdZwAz219uw,513
142
+ tnfr/validation/__init__.py,sha256=tVsCpQKc4SoBoQdKktI2pFDsaxzoeZXExSiW-ulXh5o,617
143
+ tnfr/validation/__init__.pyi,sha256=nSObG9II_9WCpYvvw3bOjIjw0iXHw8Sr0bazmXwR94k,315
144
+ tnfr/validation/compatibility.py,sha256=FNNU8VotjVv7eRFMDolixZC7vlsSZRqWLriqkH_gjLk,1788
145
+ tnfr/validation/compatibility.pyi,sha256=ELqyFWaYRgJzcuO-930v0eKxYxJFNCn2-P_AlOvSA-s,116
146
+ tnfr/validation/grammar.py,sha256=XmdRjtkvVWsC4qclG66vR37srO2vtohQgSGDTXIRpz8,4387
147
+ tnfr/validation/grammar.pyi,sha256=uavU-at-x10RBpFw_YcUC7yLepx1uo1B1sJYPGRWH0E,198
148
+ tnfr/validation/rules.py,sha256=fVJ5gX4bUkJQJsA4gBc0IMzirSUUHiGs_fj3sS5yIbM,5814
149
+ tnfr/validation/rules.pyi,sha256=WuHUQDS2o4Wrj7BRovHvwbQ6DiQSomJVgYWB0eyDL5M,305
150
+ tnfr/validation/syntax.py,sha256=O2cpQHv2FABfH7CCIcvg_Kw8zyHMzrwSF5VwjBNCrLg,4573
151
+ tnfr/validation/syntax.pyi,sha256=c8seASIj0bdS0Wof6AhupuTqkvC1x9FdmeEFk8SbETg,101
152
+ tnfr-6.0.0.dist-info/licenses/LICENSE.md,sha256=SRvvhXLrKtseuK6DARbuJffuXOXqAyk3wvF2n0t1SWA,1109
153
+ tnfr-6.0.0.dist-info/METADATA,sha256=61t5DnOqYNsIzIMnNDK8t50Bm3iKIfOwKqhN-_dSeP0,6226
154
+ tnfr-6.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
155
+ tnfr-6.0.0.dist-info/entry_points.txt,sha256=j4-QRHqeT2WnchHe_mvK7npGTLjlyfLpvRONFe9Z4MU,39
156
+ tnfr-6.0.0.dist-info/top_level.txt,sha256=Q2HJnvc5Rt2VHwVvyBTnNPT4SfmJWnCj7XUxxEvQa7c,5
157
+ tnfr-6.0.0.dist-info/RECORD,,