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
tnfr/ontosim.py CHANGED
@@ -1,140 +1,141 @@
1
- """
2
- ontosim.py — TNFR canónica
3
-
4
- Módulo de orquestación mínima que encadena:
5
- ΔNFR (campo) → Si → glifos → ecuación nodal → clamps → U’M → observadores → RE’MESH
6
- """
7
- from __future__ import annotations
8
- import networkx as nx
9
- import math
10
- import random
1
+ """Orchestrate the canonical simulation."""
2
+
3
+ from __future__ import annotations
4
+
11
5
  from collections import deque
12
-
13
- from .constants import DEFAULTS, attach_defaults
6
+ from typing import TYPE_CHECKING
7
+
8
+ from .callback_utils import CallbackEvent
9
+ from .constants import METRIC_DEFAULTS, inject_defaults, get_param
14
10
  from .dynamics import step as _step, run as _run
15
11
  from .dynamics import default_compute_delta_nfr
16
-
17
- # API de alto nivel
18
-
19
- def preparar_red(G: nx.Graph, *, override_defaults: bool = False, **overrides) -> nx.Graph:
20
- attach_defaults(G, override=override_defaults)
21
- if overrides:
12
+ from .initialization import init_node_attrs
13
+ from .glyph_history import append_metric
14
+ from .utils import cached_import
15
+
16
+ if TYPE_CHECKING: # pragma: no cover
17
+ import networkx as nx
18
+
19
+ # High-level API exports
20
+ __all__ = ("prepare_network", "step", "run")
21
+
22
+
23
+ def prepare_network(
24
+ G: "nx.Graph",
25
+ *,
26
+ init_attrs: bool = True,
27
+ override_defaults: bool = False,
28
+ **overrides,
29
+ ) -> "nx.Graph":
30
+ """Prepare ``G`` for simulation.
31
+
32
+ Parameters
33
+ ----------
34
+ init_attrs:
35
+ Run ``init_node_attrs`` when ``True`` (default), leaving node
36
+ attributes untouched when ``False``.
37
+ override_defaults:
38
+ If ``True``, :func:`inject_defaults` overwrites existing entries.
39
+ **overrides:
40
+ Parameters applied after the defaults phase.
41
+ """
42
+ inject_defaults(G, override=override_defaults)
43
+ if overrides:
22
44
  from .constants import merge_overrides
23
- merge_overrides(G, **overrides)
24
- # Inicializaciones blandas
25
- G.graph.setdefault("history", {
26
- "C_steps": [],
27
- "stable_frac": [],
28
- "phase_sync": [],
29
- "kuramoto_R": [],
30
- "sense_sigma_x": [],
31
- "sense_sigma_y": [],
32
- "sense_sigma_mag": [],
33
- "sense_sigma_angle": [],
34
- "iota": [],
35
- "glyph_load_estab": [],
36
- "glyph_load_disr": [],
37
- "Si_mean": [],
38
- "Si_hi_frac": [],
39
- "Si_lo_frac": [],
40
- "W_bar": [],
41
- "phase_kG": [],
42
- "phase_kL": [],
43
- "phase_state": [],
44
- "phase_R": [],
45
- "phase_disr": [],
46
- })
47
- tau = int(G.graph.get("REMESH_TAU", DEFAULTS["REMESH_TAU"]))
45
+
46
+ merge_overrides(G, **overrides)
47
+ # Initialize history buffers
48
+ ph_len = int(
49
+ G.graph.get(
50
+ "PHASE_HISTORY_MAXLEN", METRIC_DEFAULTS["PHASE_HISTORY_MAXLEN"]
51
+ )
52
+ )
53
+ hist_keys = [
54
+ "C_steps",
55
+ "stable_frac",
56
+ "phase_sync",
57
+ "kuramoto_R",
58
+ "sense_sigma_x",
59
+ "sense_sigma_y",
60
+ "sense_sigma_mag",
61
+ "sense_sigma_angle",
62
+ "iota",
63
+ "glyph_load_stabilizers",
64
+ "glyph_load_disr",
65
+ "Si_mean",
66
+ "Si_hi_frac",
67
+ "Si_lo_frac",
68
+ "W_bar",
69
+ "phase_kG",
70
+ "phase_kL",
71
+ ]
72
+ history = {k: [] for k in hist_keys}
73
+ history.update(
74
+ {
75
+ "phase_state": deque(maxlen=ph_len),
76
+ "phase_R": deque(maxlen=ph_len),
77
+ "phase_disr": deque(maxlen=ph_len),
78
+ }
79
+ )
80
+ history_ref = G.graph.setdefault("history", history)
81
+ # Global REMESH memory
82
+ tau = int(get_param(G, "REMESH_TAU_GLOBAL"))
48
83
  maxlen = max(2 * tau + 5, 64)
49
84
  G.graph.setdefault("_epi_hist", deque(maxlen=maxlen))
50
- # Auto-attach del observador estándar si se pide
51
- if G.graph.get("ATTACH_STD_OBSERVER", False):
52
- try:
53
- from .observers import attach_standard_observer
54
- attach_standard_observer(G)
55
- except Exception as e:
56
- G.graph.setdefault("_callback_errors", []).append(
57
- {"event":"attach_std_observer","error":repr(e)}
58
- )
59
- # Hook explícito para ΔNFR (se puede sustituir luego con dynamics.set_delta_nfr_hook)
60
- G.graph.setdefault("compute_delta_nfr", default_compute_delta_nfr)
61
- G.graph.setdefault("_dnfr_hook_name", "default_compute_delta_nfr")
62
- # Callbacks Γ(R): before_step / after_step / on_remesh
63
- G.graph.setdefault("callbacks", {
64
- "before_step": [],
65
- "after_step": [],
66
- "on_remesh": [],
67
- })
68
- G.graph.setdefault("_CALLBACKS_DOC",
69
- "Interfaz Γ(R): registrar funciones (G, ctx) en callbacks['before_step'|'after_step'|'on_remesh']")
70
-
71
- # --- Inicialización configurable de θ y νf ---
72
- seed = int(G.graph.get("RANDOM_SEED", 0))
73
- init_rand_phase = bool(G.graph.get("INIT_RANDOM_PHASE", DEFAULTS.get("INIT_RANDOM_PHASE", True)))
74
-
75
- th_min = float(G.graph.get("INIT_THETA_MIN", DEFAULTS.get("INIT_THETA_MIN", -math.pi)))
76
- th_max = float(G.graph.get("INIT_THETA_MAX", DEFAULTS.get("INIT_THETA_MAX", math.pi)))
77
-
78
- vf_mode = str(G.graph.get("INIT_VF_MODE", DEFAULTS.get("INIT_VF_MODE", "uniform"))).lower()
79
- vf_min_lim = float(G.graph.get("VF_MIN", DEFAULTS["VF_MIN"]))
80
- vf_max_lim = float(G.graph.get("VF_MAX", DEFAULTS["VF_MAX"]))
81
-
82
- vf_uniform_min = G.graph.get("INIT_VF_MIN", DEFAULTS.get("INIT_VF_MIN", None))
83
- vf_uniform_max = G.graph.get("INIT_VF_MAX", DEFAULTS.get("INIT_VF_MAX", None))
84
- if vf_uniform_min is None: vf_uniform_min = vf_min_lim
85
- if vf_uniform_max is None: vf_uniform_max = vf_max_lim
86
-
87
- vf_mean = float(G.graph.get("INIT_VF_MEAN", DEFAULTS.get("INIT_VF_MEAN", 0.5)))
88
- vf_std = float(G.graph.get("INIT_VF_STD", DEFAULTS.get("INIT_VF_STD", 0.15)))
89
- clamp_to_limits = bool(G.graph.get("INIT_VF_CLAMP_TO_LIMITS", DEFAULTS.get("INIT_VF_CLAMP_TO_LIMITS", True)))
90
-
91
- for idx, n in enumerate(G.nodes()):
92
- nd = G.nodes[n]
93
- # EPI canónico
94
- nd.setdefault("EPI", 0.0)
95
-
96
- # θ aleatoria (opt-in por flag)
97
- if init_rand_phase:
98
- th_rng = random.Random(seed + 1009 * idx)
99
- nd["θ"] = th_rng.uniform(th_min, th_max)
100
- else:
101
- nd.setdefault("θ", 0.0)
102
-
103
- # νf distribuida
104
- if vf_mode == "uniform":
105
- vf_rng = random.Random(seed * 1000003 + idx)
106
- vf = vf_rng.uniform(float(vf_uniform_min), float(vf_uniform_max))
107
- elif vf_mode == "normal":
108
- vf_rng = random.Random(seed * 1000003 + idx)
109
- # normal truncada simple (rechazo)
110
- for _ in range(16):
111
- cand = vf_rng.normalvariate(vf_mean, vf_std)
112
- if vf_min_lim <= cand <= vf_max_lim:
113
- vf = cand
114
- break
115
- else:
116
- # fallback: clamp del último candidato
117
- vf = min(max(vf_rng.normalvariate(vf_mean, vf_std), vf_min_lim), vf_max_lim)
118
- else:
119
- # fallback: conserva si existe, si no 0.5
120
- vf = float(nd.get("νf", 0.5))
121
-
122
- if clamp_to_limits:
123
- vf = min(max(vf, vf_min_lim), vf_max_lim)
124
-
125
- nd["νf"] = float(vf)
126
-
127
- return G
128
-
129
- def step(G: nx.Graph, *, dt: float | None = None, use_Si: bool = True, apply_glyphs: bool = True) -> None:
130
- _step(G, dt=dt, use_Si=use_Si, apply_glyphs=apply_glyphs)
131
-
132
- def run(G: nx.Graph, steps: int, *, dt: float | None = None, use_Si: bool = True, apply_glyphs: bool = True) -> None:
133
- _run(G, steps=steps, dt=dt, use_Si=use_Si, apply_glyphs=apply_glyphs)
134
-
135
- # Helper rápido para pruebas manuales
136
- if __name__ == "__main__":
137
- G = nx.erdos_renyi_graph(30, 0.15)
138
- preparar_red(G)
139
- run(G, 100)
140
- print("C(t) muestras:", G.graph["history"]["C_steps"][-5:])
85
+ # Auto-attach the standard observer when requested
86
+ if G.graph.get("ATTACH_STD_OBSERVER", False):
87
+ attach_standard_observer = cached_import(
88
+ "tnfr.observers",
89
+ "attach_standard_observer",
90
+ )
91
+ if attach_standard_observer is not None:
92
+ attach_standard_observer(G)
93
+ else:
94
+ append_metric(
95
+ G.graph,
96
+ "_callback_errors",
97
+ {"event": "attach_std_observer", "error": "ImportError"},
98
+ )
99
+ # Explicit hook for ΔNFR (can later be replaced with
100
+ # dynamics.set_delta_nfr_hook)
101
+ G.graph.setdefault("compute_delta_nfr", default_compute_delta_nfr)
102
+ G.graph.setdefault("_dnfr_hook_name", "default_compute_delta_nfr")
103
+ # Callbacks Γ(R): before_step / after_step / on_remesh
104
+ G.graph.setdefault(
105
+ "callbacks",
106
+ {
107
+ CallbackEvent.BEFORE_STEP.value: [],
108
+ CallbackEvent.AFTER_STEP.value: [],
109
+ CallbackEvent.ON_REMESH.value: [],
110
+ },
111
+ )
112
+ G.graph.setdefault(
113
+ "_CALLBACKS_DOC",
114
+ "Γ(R) interface: register (name, func) pairs with signature (G, ctx) "
115
+ "in callbacks['before_step'|'after_step'|'on_remesh']",
116
+ )
117
+
118
+ if init_attrs:
119
+ init_node_attrs(G, override=True)
120
+ return G
121
+
122
+
123
+ def step(
124
+ G: "nx.Graph",
125
+ *,
126
+ dt: float | None = None,
127
+ use_Si: bool = True,
128
+ apply_glyphs: bool = True,
129
+ ) -> None:
130
+ _step(G, dt=dt, use_Si=use_Si, apply_glyphs=apply_glyphs)
131
+
132
+
133
+ def run(
134
+ G: "nx.Graph",
135
+ steps: int,
136
+ *,
137
+ dt: float | None = None,
138
+ use_Si: bool = True,
139
+ apply_glyphs: bool = True,
140
+ ) -> None:
141
+ _run(G, steps=steps, dt=dt, use_Si=use_Si, apply_glyphs=apply_glyphs)
tnfr/ontosim.pyi ADDED
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from .types import TNFRConfigValue, TNFRGraph
4
+
5
+ __all__: tuple[str, ...]
6
+
7
+
8
+ def prepare_network(
9
+ G: TNFRGraph,
10
+ *,
11
+ init_attrs: bool = True,
12
+ override_defaults: bool = False,
13
+ **overrides: TNFRConfigValue,
14
+ ) -> TNFRGraph: ...
15
+
16
+
17
+ def step(
18
+ G: TNFRGraph,
19
+ *,
20
+ dt: float | None = None,
21
+ use_Si: bool = True,
22
+ apply_glyphs: bool = True,
23
+ ) -> None: ...
24
+
25
+
26
+ def run(
27
+ G: TNFRGraph,
28
+ steps: int,
29
+ *,
30
+ dt: float | None = None,
31
+ use_Si: bool = True,
32
+ apply_glyphs: bool = True,
33
+ ) -> None: ...