tnfr 4.5.2__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 (161) hide show
  1. tnfr/__init__.py +228 -49
  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 +106 -21
  7. tnfr/alias.pyi +140 -0
  8. tnfr/cache.py +666 -512
  9. tnfr/cache.pyi +232 -0
  10. tnfr/callback_utils.py +2 -9
  11. tnfr/callback_utils.pyi +105 -0
  12. tnfr/cli/__init__.py +21 -7
  13. tnfr/cli/__init__.pyi +47 -0
  14. tnfr/cli/arguments.py +42 -20
  15. tnfr/cli/arguments.pyi +33 -0
  16. tnfr/cli/execution.py +54 -20
  17. tnfr/cli/execution.pyi +80 -0
  18. tnfr/cli/utils.py +0 -2
  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.py → config/init.py} +11 -7
  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 +78 -24
  31. tnfr/constants/__init__.pyi +104 -0
  32. tnfr/constants/core.py +1 -2
  33. tnfr/constants/core.pyi +17 -0
  34. tnfr/constants/init.pyi +12 -0
  35. tnfr/constants/metric.py +4 -12
  36. tnfr/constants/metric.pyi +19 -0
  37. tnfr/constants_glyphs.py +9 -91
  38. tnfr/constants_glyphs.pyi +12 -0
  39. tnfr/dynamics/__init__.py +112 -634
  40. tnfr/dynamics/__init__.pyi +83 -0
  41. tnfr/dynamics/adaptation.py +201 -0
  42. tnfr/dynamics/aliases.py +22 -0
  43. tnfr/dynamics/coordination.py +343 -0
  44. tnfr/dynamics/dnfr.py +1936 -354
  45. tnfr/dynamics/dnfr.pyi +33 -0
  46. tnfr/dynamics/integrators.py +369 -75
  47. tnfr/dynamics/integrators.pyi +35 -0
  48. tnfr/dynamics/runtime.py +521 -0
  49. tnfr/dynamics/sampling.py +8 -5
  50. tnfr/dynamics/sampling.pyi +7 -0
  51. tnfr/dynamics/selectors.py +680 -0
  52. tnfr/execution.py +56 -41
  53. tnfr/execution.pyi +65 -0
  54. tnfr/flatten.py +7 -7
  55. tnfr/flatten.pyi +28 -0
  56. tnfr/gamma.py +54 -37
  57. tnfr/gamma.pyi +40 -0
  58. tnfr/glyph_history.py +85 -38
  59. tnfr/glyph_history.pyi +53 -0
  60. tnfr/grammar.py +19 -338
  61. tnfr/grammar.pyi +13 -0
  62. tnfr/helpers/__init__.py +110 -30
  63. tnfr/helpers/__init__.pyi +66 -0
  64. tnfr/helpers/numeric.py +1 -0
  65. tnfr/helpers/numeric.pyi +12 -0
  66. tnfr/immutable.py +55 -19
  67. tnfr/immutable.pyi +37 -0
  68. tnfr/initialization.py +12 -10
  69. tnfr/initialization.pyi +73 -0
  70. tnfr/io.py +99 -34
  71. tnfr/io.pyi +11 -0
  72. tnfr/locking.pyi +7 -0
  73. tnfr/metrics/__init__.pyi +20 -0
  74. tnfr/metrics/coherence.py +934 -294
  75. tnfr/metrics/common.py +1 -3
  76. tnfr/metrics/common.pyi +15 -0
  77. tnfr/metrics/core.py +192 -34
  78. tnfr/metrics/core.pyi +13 -0
  79. tnfr/metrics/diagnosis.py +707 -101
  80. tnfr/metrics/diagnosis.pyi +89 -0
  81. tnfr/metrics/export.py +27 -13
  82. tnfr/metrics/glyph_timing.py +218 -38
  83. tnfr/metrics/reporting.py +22 -18
  84. tnfr/metrics/reporting.pyi +12 -0
  85. tnfr/metrics/sense_index.py +199 -25
  86. tnfr/metrics/sense_index.pyi +9 -0
  87. tnfr/metrics/trig.py +53 -18
  88. tnfr/metrics/trig.pyi +12 -0
  89. tnfr/metrics/trig_cache.py +3 -7
  90. tnfr/metrics/trig_cache.pyi +10 -0
  91. tnfr/node.py +148 -125
  92. tnfr/node.pyi +161 -0
  93. tnfr/observers.py +44 -30
  94. tnfr/observers.pyi +46 -0
  95. tnfr/ontosim.py +14 -13
  96. tnfr/ontosim.pyi +33 -0
  97. tnfr/operators/__init__.py +84 -52
  98. tnfr/operators/__init__.pyi +31 -0
  99. tnfr/operators/definitions.py +181 -0
  100. tnfr/operators/definitions.pyi +92 -0
  101. tnfr/operators/jitter.py +86 -23
  102. tnfr/operators/jitter.pyi +11 -0
  103. tnfr/operators/registry.py +80 -0
  104. tnfr/operators/registry.pyi +15 -0
  105. tnfr/operators/remesh.py +141 -57
  106. tnfr/presets.py +9 -54
  107. tnfr/presets.pyi +7 -0
  108. tnfr/py.typed +0 -0
  109. tnfr/rng.py +259 -73
  110. tnfr/rng.pyi +14 -0
  111. tnfr/selector.py +24 -17
  112. tnfr/selector.pyi +19 -0
  113. tnfr/sense.py +55 -43
  114. tnfr/sense.pyi +30 -0
  115. tnfr/structural.py +44 -267
  116. tnfr/structural.pyi +46 -0
  117. tnfr/telemetry/__init__.py +13 -0
  118. tnfr/telemetry/verbosity.py +37 -0
  119. tnfr/tokens.py +3 -2
  120. tnfr/tokens.pyi +41 -0
  121. tnfr/trace.py +272 -82
  122. tnfr/trace.pyi +68 -0
  123. tnfr/types.py +345 -6
  124. tnfr/types.pyi +145 -0
  125. tnfr/utils/__init__.py +158 -0
  126. tnfr/utils/__init__.pyi +133 -0
  127. tnfr/utils/cache.py +755 -0
  128. tnfr/utils/cache.pyi +156 -0
  129. tnfr/{collections_utils.py → utils/data.py} +57 -90
  130. tnfr/utils/data.pyi +73 -0
  131. tnfr/utils/graph.py +87 -0
  132. tnfr/utils/graph.pyi +10 -0
  133. tnfr/utils/init.py +746 -0
  134. tnfr/utils/init.pyi +85 -0
  135. tnfr/{json_utils.py → utils/io.py} +13 -18
  136. tnfr/utils/io.pyi +10 -0
  137. tnfr/utils/validators.py +130 -0
  138. tnfr/utils/validators.pyi +19 -0
  139. tnfr/validation/__init__.py +25 -0
  140. tnfr/validation/__init__.pyi +17 -0
  141. tnfr/validation/compatibility.py +59 -0
  142. tnfr/validation/compatibility.pyi +8 -0
  143. tnfr/validation/grammar.py +149 -0
  144. tnfr/validation/grammar.pyi +11 -0
  145. tnfr/validation/rules.py +194 -0
  146. tnfr/validation/rules.pyi +18 -0
  147. tnfr/validation/syntax.py +151 -0
  148. tnfr/validation/syntax.pyi +7 -0
  149. tnfr-6.0.0.dist-info/METADATA +135 -0
  150. tnfr-6.0.0.dist-info/RECORD +157 -0
  151. tnfr/graph_utils.py +0 -84
  152. tnfr/import_utils.py +0 -228
  153. tnfr/logging_utils.py +0 -116
  154. tnfr/validators.py +0 -84
  155. tnfr/value_utils.py +0 -59
  156. tnfr-4.5.2.dist-info/METADATA +0 -379
  157. tnfr-4.5.2.dist-info/RECORD +0 -67
  158. {tnfr-4.5.2.dist-info → tnfr-6.0.0.dist-info}/WHEEL +0 -0
  159. {tnfr-4.5.2.dist-info → tnfr-6.0.0.dist-info}/entry_points.txt +0 -0
  160. {tnfr-4.5.2.dist-info → tnfr-6.0.0.dist-info}/licenses/LICENSE.md +0 -0
  161. {tnfr-4.5.2.dist-info → tnfr-6.0.0.dist-info}/top_level.txt +0 -0
tnfr/metrics/common.py CHANGED
@@ -6,12 +6,10 @@ from types import MappingProxyType
6
6
  from typing import Any, Iterable, Mapping, Sequence
7
7
 
8
8
  from ..alias import collect_attr, get_attr, multi_recompute_abs_max
9
- from ..collections_utils import normalize_weights
10
9
  from ..constants import DEFAULTS, get_aliases
11
- from ..cache import edge_version_cache
12
10
  from ..helpers.numeric import clamp01, kahan_sum_nd
13
- from ..import_utils import get_numpy
14
11
  from ..types import GraphLike
12
+ from ..utils import edge_version_cache, get_numpy, normalize_weights
15
13
 
16
14
  ALIAS_DNFR = get_aliases("DNFR")
17
15
  ALIAS_D2EPI = get_aliases("D2EPI")
@@ -0,0 +1,15 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ GraphLike: Any
8
+ _get_vf_dnfr_max: Any
9
+ compute_coherence: Any
10
+ compute_dnfr_accel_max: Any
11
+ ensure_neighbors_map: Any
12
+ merge_and_normalize_weights: Any
13
+ merge_graph_weights: Any
14
+ min_max_range: Any
15
+ normalize_dnfr: Any
tnfr/metrics/core.py CHANGED
@@ -2,12 +2,31 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any
5
+ from collections.abc import Mapping
6
+ from typing import Any, NamedTuple, cast
7
+
8
+ from ..types import (
9
+ GlyphSelector,
10
+ NodeId,
11
+ SelectorPreselectionChoices,
12
+ SelectorPreselectionMetrics,
13
+ SelectorPreselectionPayload,
14
+ TNFRGraph,
15
+ TraceCallback,
16
+ TraceFieldFn,
17
+ TraceFieldMap,
18
+ TraceFieldRegistry,
19
+ )
6
20
 
7
21
  from ..callback_utils import CallbackEvent, callback_manager
8
22
  from ..constants import get_param
9
23
  from ..glyph_history import append_metric, ensure_history
10
- from ..logging_utils import get_logger
24
+ from ..utils import get_logger
25
+ from ..telemetry.verbosity import (
26
+ TelemetryVerbosity,
27
+ TELEMETRY_VERBOSITY_DEFAULT,
28
+ TELEMETRY_VERBOSITY_LEVELS,
29
+ )
11
30
  from .coherence import (
12
31
  _aggregate_si,
13
32
  _track_stability,
@@ -15,9 +34,10 @@ from .coherence import (
15
34
  _update_phase_sync,
16
35
  _update_sigma,
17
36
  register_coherence_callbacks,
37
+ GLYPH_LOAD_STABILIZERS_KEY,
18
38
  )
19
39
  from .diagnosis import register_diagnosis_callbacks
20
- from .glyph_timing import _compute_advanced_metrics
40
+ from .glyph_timing import _compute_advanced_metrics, GlyphMetricsHistory
21
41
  from .reporting import (
22
42
  Tg_by_node,
23
43
  Tg_global,
@@ -29,6 +49,16 @@ from .reporting import (
29
49
  logger = get_logger(__name__)
30
50
 
31
51
  __all__ = [
52
+ "TNFRGraph",
53
+ "NodeId",
54
+ "GlyphSelector",
55
+ "SelectorPreselectionMetrics",
56
+ "SelectorPreselectionChoices",
57
+ "SelectorPreselectionPayload",
58
+ "TraceCallback",
59
+ "TraceFieldFn",
60
+ "TraceFieldMap",
61
+ "TraceFieldRegistry",
32
62
  "_metrics_step",
33
63
  "register_metrics_callbacks",
34
64
  "Tg_global",
@@ -39,32 +69,124 @@ __all__ = [
39
69
  ]
40
70
 
41
71
 
42
- def _metrics_step(G, ctx: dict[str, Any] | None = None):
72
+ class MetricsVerbositySpec(NamedTuple):
73
+ """Runtime configuration for metrics verbosity tiers."""
74
+
75
+ name: str
76
+ enable_phase_sync: bool
77
+ enable_sigma: bool
78
+ enable_aggregate_si: bool
79
+ enable_advanced: bool
80
+ attach_coherence_hooks: bool
81
+ attach_diagnosis_hooks: bool
82
+
83
+
84
+ METRICS_VERBOSITY_DEFAULT = TELEMETRY_VERBOSITY_DEFAULT
85
+
86
+ _METRICS_VERBOSITY_PRESETS: dict[str, MetricsVerbositySpec] = {}
87
+
88
+
89
+ def _register_metrics_preset(spec: MetricsVerbositySpec) -> None:
90
+ if spec.name not in TELEMETRY_VERBOSITY_LEVELS:
91
+ raise ValueError(
92
+ "Unknown metrics verbosity '%s'; use %s" % (
93
+ spec.name,
94
+ ", ".join(TELEMETRY_VERBOSITY_LEVELS),
95
+ )
96
+ )
97
+ _METRICS_VERBOSITY_PRESETS[spec.name] = spec
98
+
99
+
100
+ _register_metrics_preset(
101
+ MetricsVerbositySpec(
102
+ name=TelemetryVerbosity.BASIC.value,
103
+ enable_phase_sync=False,
104
+ enable_sigma=False,
105
+ enable_aggregate_si=False,
106
+ enable_advanced=False,
107
+ attach_coherence_hooks=False,
108
+ attach_diagnosis_hooks=False,
109
+ )
110
+ )
111
+
112
+ _detailed_spec = MetricsVerbositySpec(
113
+ name=TelemetryVerbosity.DETAILED.value,
114
+ enable_phase_sync=True,
115
+ enable_sigma=True,
116
+ enable_aggregate_si=True,
117
+ enable_advanced=False,
118
+ attach_coherence_hooks=True,
119
+ attach_diagnosis_hooks=False,
120
+ )
121
+ _register_metrics_preset(_detailed_spec)
122
+ _register_metrics_preset(
123
+ _detailed_spec._replace(
124
+ name=TelemetryVerbosity.DEBUG.value,
125
+ enable_advanced=True,
126
+ attach_diagnosis_hooks=True,
127
+ )
128
+ )
129
+
130
+
131
+ _METRICS_BASE_HISTORY_KEYS = ("C_steps", "stable_frac", "delta_Si", "B")
132
+ _METRICS_PHASE_HISTORY_KEYS = ("phase_sync", "kuramoto_R")
133
+ _METRICS_SIGMA_HISTORY_KEYS = (
134
+ GLYPH_LOAD_STABILIZERS_KEY,
135
+ "glyph_load_disr",
136
+ "sense_sigma_x",
137
+ "sense_sigma_y",
138
+ "sense_sigma_mag",
139
+ "sense_sigma_angle",
140
+ )
141
+ _METRICS_SI_HISTORY_KEYS = ("Si_mean", "Si_hi_frac", "Si_lo_frac")
142
+
143
+
144
+ def _resolve_metrics_verbosity(cfg: Mapping[str, Any]) -> MetricsVerbositySpec:
145
+ """Return the preset matching ``cfg['verbosity']``."""
146
+
147
+ raw_value = cfg.get("verbosity", METRICS_VERBOSITY_DEFAULT)
148
+ key = str(raw_value).lower()
149
+ spec = _METRICS_VERBOSITY_PRESETS.get(key)
150
+ if spec is not None:
151
+ return spec
152
+ logger.warning(
153
+ "Unknown METRICS verbosity '%s'; falling back to '%s'",
154
+ raw_value,
155
+ METRICS_VERBOSITY_DEFAULT,
156
+ )
157
+ return _METRICS_VERBOSITY_PRESETS[METRICS_VERBOSITY_DEFAULT]
158
+
159
+
160
+ def _metrics_step(G: TNFRGraph, ctx: dict[str, Any] | None = None) -> None:
43
161
  """Update operational TNFR metrics per step."""
44
162
 
45
163
  del ctx
46
164
 
47
- cfg = get_param(G, "METRICS")
165
+ cfg = cast(Mapping[str, Any], get_param(G, "METRICS"))
48
166
  if not cfg.get("enabled", True):
49
167
  return
50
168
 
169
+ spec = _resolve_metrics_verbosity(cfg)
51
170
  hist = ensure_history(G)
171
+ if "glyph_load_estab" in hist:
172
+ raise ValueError(
173
+ "History payloads using 'glyph_load_estab' are no longer supported. "
174
+ "Rename the series to 'glyph_load_stabilizers' before loading the graph."
175
+ )
52
176
  metrics_sentinel_key = "_metrics_history_id"
53
177
  history_id = id(hist)
54
178
  if G.graph.get(metrics_sentinel_key) != history_id:
55
- for k in (
56
- "C_steps",
57
- "stable_frac",
58
- "phase_sync",
59
- "glyph_load_estab",
60
- "glyph_load_disr",
61
- "Si_mean",
62
- "Si_hi_frac",
63
- "Si_lo_frac",
64
- "delta_Si",
65
- "B",
66
- ):
67
- hist.setdefault(k, [])
179
+ for key in _METRICS_BASE_HISTORY_KEYS:
180
+ hist.setdefault(key, [])
181
+ if spec.enable_phase_sync:
182
+ for key in _METRICS_PHASE_HISTORY_KEYS:
183
+ hist.setdefault(key, [])
184
+ if spec.enable_sigma:
185
+ for key in _METRICS_SIGMA_HISTORY_KEYS:
186
+ hist.setdefault(key, [])
187
+ if spec.enable_aggregate_si:
188
+ for key in _METRICS_SI_HISTORY_KEYS:
189
+ hist.setdefault(key, [])
68
190
  G.graph[metrics_sentinel_key] = history_id
69
191
 
70
192
  dt = float(get_param(G, "DT"))
@@ -73,29 +195,65 @@ def _metrics_step(G, ctx: dict[str, Any] | None = None):
73
195
  t = float(G.graph.get("_t", 0.0))
74
196
 
75
197
  _update_coherence(G, hist)
76
- _track_stability(G, hist, dt, eps_dnfr, eps_depi)
198
+
199
+ raw_jobs = cfg.get("n_jobs")
200
+ metrics_jobs: int | None
77
201
  try:
78
- _update_phase_sync(G, hist)
79
- _update_sigma(G, hist)
80
- if hist.get("C_steps") and hist.get("stable_frac"):
81
- append_metric(
82
- hist,
83
- "iota",
84
- hist["C_steps"][-1] * hist["stable_frac"][-1],
85
- )
86
- except (KeyError, AttributeError, TypeError) as exc:
87
- logger.debug("observer update failed: %s", exc)
202
+ metrics_jobs = None if raw_jobs is None else int(raw_jobs)
203
+ except (TypeError, ValueError):
204
+ metrics_jobs = None
205
+ else:
206
+ if metrics_jobs <= 0:
207
+ metrics_jobs = None
208
+
209
+ _track_stability(
210
+ G,
211
+ hist,
212
+ dt,
213
+ eps_dnfr,
214
+ eps_depi,
215
+ n_jobs=metrics_jobs,
216
+ )
217
+ if spec.enable_phase_sync or spec.enable_sigma:
218
+ try:
219
+ if spec.enable_phase_sync:
220
+ _update_phase_sync(G, hist)
221
+ if spec.enable_sigma:
222
+ _update_sigma(G, hist)
223
+ except (KeyError, AttributeError, TypeError) as exc:
224
+ logger.debug("observer update failed: %s", exc)
225
+
226
+ if hist.get("C_steps") and hist.get("stable_frac"):
227
+ append_metric(
228
+ hist,
229
+ "iota",
230
+ hist["C_steps"][-1] * hist["stable_frac"][-1],
231
+ )
232
+
233
+ if spec.enable_aggregate_si:
234
+ _aggregate_si(G, hist, n_jobs=metrics_jobs)
88
235
 
89
- _aggregate_si(G, hist)
90
- _compute_advanced_metrics(G, hist, t, dt, cfg)
236
+ if spec.enable_advanced:
237
+ _compute_advanced_metrics(
238
+ G,
239
+ cast(GlyphMetricsHistory, hist),
240
+ t,
241
+ dt,
242
+ cfg,
243
+ n_jobs=metrics_jobs,
244
+ )
91
245
 
92
246
 
93
- def register_metrics_callbacks(G) -> None:
247
+ def register_metrics_callbacks(G: TNFRGraph) -> None:
248
+ cfg = cast(Mapping[str, Any], get_param(G, "METRICS"))
249
+ spec = _resolve_metrics_verbosity(cfg)
94
250
  callback_manager.register_callback(
95
251
  G,
96
252
  event=CallbackEvent.AFTER_STEP.value,
97
253
  func=_metrics_step,
98
254
  name="metrics_step",
99
255
  )
100
- register_coherence_callbacks(G)
101
- register_diagnosis_callbacks(G)
256
+ if spec.attach_coherence_hooks:
257
+ register_coherence_callbacks(G)
258
+ if spec.attach_diagnosis_hooks:
259
+ register_diagnosis_callbacks(G)
tnfr/metrics/core.pyi ADDED
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ Tg_by_node: Any
8
+ Tg_global: Any
9
+ _metrics_step: Any
10
+ glyph_top: Any
11
+ glyphogram_series: Any
12
+ latency_series: Any
13
+ register_metrics_callbacks: Any