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.
- tnfr/__init__.py +270 -90
- tnfr/__init__.pyi +40 -0
- tnfr/_compat.py +11 -0
- tnfr/_version.py +7 -0
- tnfr/_version.pyi +7 -0
- tnfr/alias.py +631 -0
- tnfr/alias.pyi +140 -0
- tnfr/cache.py +732 -0
- tnfr/cache.pyi +232 -0
- tnfr/callback_utils.py +381 -0
- tnfr/callback_utils.pyi +105 -0
- tnfr/cli/__init__.py +89 -0
- tnfr/cli/__init__.pyi +47 -0
- tnfr/cli/arguments.py +199 -0
- tnfr/cli/arguments.pyi +33 -0
- tnfr/cli/execution.py +322 -0
- tnfr/cli/execution.pyi +80 -0
- tnfr/cli/utils.py +34 -0
- tnfr/cli/utils.pyi +8 -0
- tnfr/config/__init__.py +12 -0
- tnfr/config/__init__.pyi +8 -0
- tnfr/config/constants.py +104 -0
- tnfr/config/constants.pyi +12 -0
- tnfr/config/init.py +36 -0
- tnfr/config/init.pyi +8 -0
- tnfr/config/operator_names.py +106 -0
- tnfr/config/operator_names.pyi +28 -0
- tnfr/config/presets.py +104 -0
- tnfr/config/presets.pyi +7 -0
- tnfr/constants/__init__.py +228 -0
- tnfr/constants/__init__.pyi +104 -0
- tnfr/constants/core.py +158 -0
- tnfr/constants/core.pyi +17 -0
- tnfr/constants/init.py +31 -0
- tnfr/constants/init.pyi +12 -0
- tnfr/constants/metric.py +102 -0
- tnfr/constants/metric.pyi +19 -0
- tnfr/constants_glyphs.py +16 -0
- tnfr/constants_glyphs.pyi +12 -0
- tnfr/dynamics/__init__.py +136 -0
- tnfr/dynamics/__init__.pyi +83 -0
- tnfr/dynamics/adaptation.py +201 -0
- tnfr/dynamics/aliases.py +22 -0
- tnfr/dynamics/coordination.py +343 -0
- tnfr/dynamics/dnfr.py +2315 -0
- tnfr/dynamics/dnfr.pyi +33 -0
- tnfr/dynamics/integrators.py +561 -0
- tnfr/dynamics/integrators.pyi +35 -0
- tnfr/dynamics/runtime.py +521 -0
- tnfr/dynamics/sampling.py +34 -0
- tnfr/dynamics/sampling.pyi +7 -0
- tnfr/dynamics/selectors.py +680 -0
- tnfr/execution.py +216 -0
- tnfr/execution.pyi +65 -0
- tnfr/flatten.py +283 -0
- tnfr/flatten.pyi +28 -0
- tnfr/gamma.py +320 -89
- tnfr/gamma.pyi +40 -0
- tnfr/glyph_history.py +337 -0
- tnfr/glyph_history.pyi +53 -0
- tnfr/grammar.py +23 -153
- tnfr/grammar.pyi +13 -0
- tnfr/helpers/__init__.py +151 -0
- tnfr/helpers/__init__.pyi +66 -0
- tnfr/helpers/numeric.py +88 -0
- tnfr/helpers/numeric.pyi +12 -0
- tnfr/immutable.py +214 -0
- tnfr/immutable.pyi +37 -0
- tnfr/initialization.py +199 -0
- tnfr/initialization.pyi +73 -0
- tnfr/io.py +311 -0
- tnfr/io.pyi +11 -0
- tnfr/locking.py +37 -0
- tnfr/locking.pyi +7 -0
- tnfr/metrics/__init__.py +41 -0
- tnfr/metrics/__init__.pyi +20 -0
- tnfr/metrics/coherence.py +1469 -0
- tnfr/metrics/common.py +149 -0
- tnfr/metrics/common.pyi +15 -0
- tnfr/metrics/core.py +259 -0
- tnfr/metrics/core.pyi +13 -0
- tnfr/metrics/diagnosis.py +840 -0
- tnfr/metrics/diagnosis.pyi +89 -0
- tnfr/metrics/export.py +151 -0
- tnfr/metrics/glyph_timing.py +369 -0
- tnfr/metrics/reporting.py +152 -0
- tnfr/metrics/reporting.pyi +12 -0
- tnfr/metrics/sense_index.py +294 -0
- tnfr/metrics/sense_index.pyi +9 -0
- tnfr/metrics/trig.py +216 -0
- tnfr/metrics/trig.pyi +12 -0
- tnfr/metrics/trig_cache.py +105 -0
- tnfr/metrics/trig_cache.pyi +10 -0
- tnfr/node.py +255 -177
- tnfr/node.pyi +161 -0
- tnfr/observers.py +154 -150
- tnfr/observers.pyi +46 -0
- tnfr/ontosim.py +135 -134
- tnfr/ontosim.pyi +33 -0
- tnfr/operators/__init__.py +452 -0
- tnfr/operators/__init__.pyi +31 -0
- tnfr/operators/definitions.py +181 -0
- tnfr/operators/definitions.pyi +92 -0
- tnfr/operators/jitter.py +266 -0
- tnfr/operators/jitter.pyi +11 -0
- tnfr/operators/registry.py +80 -0
- tnfr/operators/registry.pyi +15 -0
- tnfr/operators/remesh.py +569 -0
- tnfr/presets.py +10 -23
- tnfr/presets.pyi +7 -0
- tnfr/py.typed +0 -0
- tnfr/rng.py +440 -0
- tnfr/rng.pyi +14 -0
- tnfr/selector.py +217 -0
- tnfr/selector.pyi +19 -0
- tnfr/sense.py +307 -142
- tnfr/sense.pyi +30 -0
- tnfr/structural.py +69 -164
- tnfr/structural.pyi +46 -0
- tnfr/telemetry/__init__.py +13 -0
- tnfr/telemetry/verbosity.py +37 -0
- tnfr/tokens.py +61 -0
- tnfr/tokens.pyi +41 -0
- tnfr/trace.py +520 -95
- tnfr/trace.pyi +68 -0
- tnfr/types.py +382 -17
- tnfr/types.pyi +145 -0
- tnfr/utils/__init__.py +158 -0
- tnfr/utils/__init__.pyi +133 -0
- tnfr/utils/cache.py +755 -0
- tnfr/utils/cache.pyi +156 -0
- tnfr/utils/data.py +267 -0
- tnfr/utils/data.pyi +73 -0
- tnfr/utils/graph.py +87 -0
- tnfr/utils/graph.pyi +10 -0
- tnfr/utils/init.py +746 -0
- tnfr/utils/init.pyi +85 -0
- tnfr/utils/io.py +157 -0
- tnfr/utils/io.pyi +10 -0
- tnfr/utils/validators.py +130 -0
- tnfr/utils/validators.pyi +19 -0
- tnfr/validation/__init__.py +25 -0
- tnfr/validation/__init__.pyi +17 -0
- tnfr/validation/compatibility.py +59 -0
- tnfr/validation/compatibility.pyi +8 -0
- tnfr/validation/grammar.py +149 -0
- tnfr/validation/grammar.pyi +11 -0
- tnfr/validation/rules.py +194 -0
- tnfr/validation/rules.pyi +18 -0
- tnfr/validation/syntax.py +151 -0
- tnfr/validation/syntax.pyi +7 -0
- tnfr-6.0.0.dist-info/METADATA +135 -0
- tnfr-6.0.0.dist-info/RECORD +157 -0
- tnfr/cli.py +0 -322
- tnfr/config.py +0 -41
- tnfr/constants.py +0 -277
- tnfr/dynamics.py +0 -814
- tnfr/helpers.py +0 -264
- tnfr/main.py +0 -47
- tnfr/metrics.py +0 -597
- tnfr/operators.py +0 -525
- tnfr/program.py +0 -176
- tnfr/scenarios.py +0 -34
- tnfr/validators.py +0 -38
- tnfr-4.5.1.dist-info/METADATA +0 -221
- tnfr-4.5.1.dist-info/RECORD +0 -28
- {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/WHEEL +0 -0
- {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/entry_points.txt +0 -0
- {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/licenses/LICENSE.md +0 -0
- {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/top_level.txt +0 -0
tnfr/cli.py
DELETED
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
import argparse
|
|
3
|
-
import json
|
|
4
|
-
from typing import Any, Dict, List, Optional
|
|
5
|
-
|
|
6
|
-
try: # pragma: no cover - opcional
|
|
7
|
-
import yaml # type: ignore
|
|
8
|
-
except Exception: # pragma: no cover - yaml es opcional
|
|
9
|
-
yaml = None
|
|
10
|
-
|
|
11
|
-
import networkx as nx
|
|
12
|
-
|
|
13
|
-
from .constants import inject_defaults, DEFAULTS
|
|
14
|
-
from .sense import register_sigma_callback, sigma_series, sigma_rose
|
|
15
|
-
from .metrics import (
|
|
16
|
-
register_metrics_callbacks,
|
|
17
|
-
Tg_global,
|
|
18
|
-
latency_series,
|
|
19
|
-
glifogram_series,
|
|
20
|
-
glyph_top,
|
|
21
|
-
export_history,
|
|
22
|
-
)
|
|
23
|
-
from .trace import register_trace
|
|
24
|
-
from .program import play, seq, block, wait, target
|
|
25
|
-
from .dynamics import step, _update_history, default_glyph_selector, parametric_glyph_selector, validate_canon
|
|
26
|
-
from .gamma import GAMMA_REGISTRY
|
|
27
|
-
from .scenarios import build_graph
|
|
28
|
-
from .presets import get_preset
|
|
29
|
-
from .config import apply_config
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def _save_json(path: str, data: Any) -> None:
|
|
33
|
-
with open(path, "w", encoding="utf-8") as f:
|
|
34
|
-
json.dump(data, f, ensure_ascii=False, indent=2)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def _str2bool(s: str) -> bool:
|
|
38
|
-
s = s.lower()
|
|
39
|
-
if s in {"true", "1", "yes", "y"}:
|
|
40
|
-
return True
|
|
41
|
-
if s in {"false", "0", "no", "n"}:
|
|
42
|
-
return False
|
|
43
|
-
raise argparse.ArgumentTypeError("expected true/false")
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def _args_to_dict(args: argparse.Namespace, prefix: str) -> Dict[str, Any]:
|
|
47
|
-
out: Dict[str, Any] = {}
|
|
48
|
-
pref = prefix.replace(".", "_")
|
|
49
|
-
for k, v in vars(args).items():
|
|
50
|
-
if k.startswith(pref) and v is not None:
|
|
51
|
-
out[k[len(pref):]] = v
|
|
52
|
-
return out
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def _load_sequence(path: str) -> List[Any]:
|
|
56
|
-
with open(path, "r", encoding="utf-8") as f:
|
|
57
|
-
text = f.read()
|
|
58
|
-
if path.endswith(".yaml") or path.endswith(".yml"):
|
|
59
|
-
if not yaml:
|
|
60
|
-
raise RuntimeError("pyyaml no está instalado, usa JSON o instala pyyaml")
|
|
61
|
-
data = yaml.safe_load(text)
|
|
62
|
-
else:
|
|
63
|
-
data = json.loads(text)
|
|
64
|
-
|
|
65
|
-
def parse_token(tok: Any):
|
|
66
|
-
if isinstance(tok, str):
|
|
67
|
-
return tok
|
|
68
|
-
if isinstance(tok, dict):
|
|
69
|
-
if "WAIT" in tok:
|
|
70
|
-
return wait(int(tok["WAIT"]))
|
|
71
|
-
if "TARGET" in tok:
|
|
72
|
-
return target(tok["TARGET"])
|
|
73
|
-
if "THOL" in tok:
|
|
74
|
-
spec = tok["THOL"] or {}
|
|
75
|
-
b = [_parse_inner(x) for x in spec.get("body", [])]
|
|
76
|
-
return block(*b, repeat=int(spec.get("repeat", 1)), close=spec.get("close"))
|
|
77
|
-
raise ValueError(f"Token inválido: {tok}")
|
|
78
|
-
|
|
79
|
-
def _parse_inner(x: Any):
|
|
80
|
-
return parse_token(x)
|
|
81
|
-
|
|
82
|
-
return [parse_token(t) for t in data]
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def _attach_callbacks(G: nx.Graph) -> None:
|
|
86
|
-
inject_defaults(G, DEFAULTS)
|
|
87
|
-
register_sigma_callback(G)
|
|
88
|
-
register_metrics_callbacks(G)
|
|
89
|
-
register_trace(G)
|
|
90
|
-
_update_history(G)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def cmd_run(args: argparse.Namespace) -> int:
|
|
94
|
-
G = build_graph(n=args.nodes, topology=args.topology, seed=args.seed)
|
|
95
|
-
if getattr(args, "config", None):
|
|
96
|
-
apply_config(G, args.config)
|
|
97
|
-
_attach_callbacks(G)
|
|
98
|
-
validate_canon(G)
|
|
99
|
-
if args.dt is not None:
|
|
100
|
-
G.graph["DT"] = float(args.dt)
|
|
101
|
-
if args.integrator is not None:
|
|
102
|
-
G.graph["INTEGRATOR_METHOD"] = str(args.integrator)
|
|
103
|
-
if getattr(args, "remesh_mode", None):
|
|
104
|
-
G.graph["REMESH_MODE"] = str(args.remesh_mode)
|
|
105
|
-
gcanon = dict(DEFAULTS["GRAMMAR_CANON"])
|
|
106
|
-
gcanon.update(_args_to_dict(args, prefix="grammar."))
|
|
107
|
-
if hasattr(args, "grammar_canon") and args.grammar_canon is not None:
|
|
108
|
-
gcanon["enabled"] = bool(args.grammar_canon)
|
|
109
|
-
G.graph.setdefault("GRAMMAR_CANON", {}).update(gcanon)
|
|
110
|
-
if args.glyph_hysteresis_window is not None:
|
|
111
|
-
G.graph["GLYPH_HYSTERESIS_WINDOW"] = int(args.glyph_hysteresis_window)
|
|
112
|
-
G.graph["glyph_selector"] = default_glyph_selector if args.selector == "basic" else parametric_glyph_selector
|
|
113
|
-
G.graph["GAMMA"] = {
|
|
114
|
-
"type": args.gamma_type,
|
|
115
|
-
"beta": args.gamma_beta,
|
|
116
|
-
"R0": args.gamma_R0,
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if args.preset:
|
|
120
|
-
program = get_preset(args.preset)
|
|
121
|
-
play(G, program)
|
|
122
|
-
else:
|
|
123
|
-
steps = int(args.steps or 100)
|
|
124
|
-
for _ in range(steps):
|
|
125
|
-
step(G)
|
|
126
|
-
|
|
127
|
-
if args.save_history:
|
|
128
|
-
_save_json(args.save_history, G.graph.get("history", {}))
|
|
129
|
-
if args.export_history_base:
|
|
130
|
-
export_history(G, args.export_history_base, fmt=args.export_format)
|
|
131
|
-
|
|
132
|
-
# Resúmenes rápidos (si están activados)
|
|
133
|
-
if G.graph.get("COHERENCE", DEFAULTS["COHERENCE"]).get("enabled", True):
|
|
134
|
-
Wstats = G.graph.get("history", {}).get(
|
|
135
|
-
G.graph.get("COHERENCE", DEFAULTS["COHERENCE"]).get("stats_history_key", "W_stats"), []
|
|
136
|
-
)
|
|
137
|
-
if Wstats:
|
|
138
|
-
print("[COHERENCE] último paso:", Wstats[-1])
|
|
139
|
-
if G.graph.get("DIAGNOSIS", DEFAULTS["DIAGNOSIS"]).get("enabled", True):
|
|
140
|
-
last_diag = G.graph.get("history", {}).get(
|
|
141
|
-
G.graph.get("DIAGNOSIS", DEFAULTS["DIAGNOSIS"]).get("history_key", "nodal_diag"), []
|
|
142
|
-
)
|
|
143
|
-
if last_diag:
|
|
144
|
-
sample = list(last_diag[-1].values())[:3]
|
|
145
|
-
print("[DIAGNOSIS] ejemplo:", sample)
|
|
146
|
-
|
|
147
|
-
if args.summary:
|
|
148
|
-
tg = Tg_global(G, normalize=True)
|
|
149
|
-
lat = latency_series(G)
|
|
150
|
-
print("Top operadores por Tg:", glyph_top(G, k=5))
|
|
151
|
-
if lat["value"]:
|
|
152
|
-
print("Latencia media:", sum(lat["value"]) / max(1, len(lat["value"])) )
|
|
153
|
-
return 0
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
def cmd_sequence(args: argparse.Namespace) -> int:
|
|
157
|
-
G = build_graph(n=args.nodes, topology=args.topology, seed=args.seed)
|
|
158
|
-
if getattr(args, "config", None):
|
|
159
|
-
apply_config(G, args.config)
|
|
160
|
-
_attach_callbacks(G)
|
|
161
|
-
validate_canon(G)
|
|
162
|
-
if args.dt is not None:
|
|
163
|
-
G.graph["DT"] = float(args.dt)
|
|
164
|
-
if args.integrator is not None:
|
|
165
|
-
G.graph["INTEGRATOR_METHOD"] = str(args.integrator)
|
|
166
|
-
if getattr(args, "remesh_mode", None):
|
|
167
|
-
G.graph["REMESH_MODE"] = str(args.remesh_mode)
|
|
168
|
-
gcanon = dict(DEFAULTS["GRAMMAR_CANON"])
|
|
169
|
-
gcanon.update(_args_to_dict(args, prefix="grammar."))
|
|
170
|
-
if hasattr(args, "grammar_canon") and args.grammar_canon is not None:
|
|
171
|
-
gcanon["enabled"] = bool(args.grammar_canon)
|
|
172
|
-
G.graph.setdefault("GRAMMAR_CANON", {}).update(gcanon)
|
|
173
|
-
if args.glyph_hysteresis_window is not None:
|
|
174
|
-
G.graph["GLYPH_HYSTERESIS_WINDOW"] = int(args.glyph_hysteresis_window)
|
|
175
|
-
G.graph["glyph_selector"] = default_glyph_selector if args.selector == "basic" else parametric_glyph_selector
|
|
176
|
-
G.graph["GAMMA"] = {
|
|
177
|
-
"type": args.gamma_type,
|
|
178
|
-
"beta": args.gamma_beta,
|
|
179
|
-
"R0": args.gamma_R0,
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if args.preset:
|
|
183
|
-
program = get_preset(args.preset)
|
|
184
|
-
elif args.sequence_file:
|
|
185
|
-
program = _load_sequence(args.sequence_file)
|
|
186
|
-
else:
|
|
187
|
-
program = seq("A’L", "E’N", "I’L", block("O’Z", "Z’HIR", "I’L", repeat=1), "R’A", "SH’A")
|
|
188
|
-
|
|
189
|
-
play(G, program)
|
|
190
|
-
|
|
191
|
-
if args.save_history:
|
|
192
|
-
_save_json(args.save_history, G.graph.get("history", {}))
|
|
193
|
-
if args.export_history_base:
|
|
194
|
-
export_history(G, args.export_history_base, fmt=args.export_format)
|
|
195
|
-
return 0
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
def cmd_metrics(args: argparse.Namespace) -> int:
|
|
199
|
-
G = build_graph(n=args.nodes, topology=args.topology, seed=args.seed)
|
|
200
|
-
if getattr(args, "config", None):
|
|
201
|
-
apply_config(G, args.config)
|
|
202
|
-
_attach_callbacks(G)
|
|
203
|
-
validate_canon(G)
|
|
204
|
-
if args.dt is not None:
|
|
205
|
-
G.graph["DT"] = float(args.dt)
|
|
206
|
-
if args.integrator is not None:
|
|
207
|
-
G.graph["INTEGRATOR_METHOD"] = str(args.integrator)
|
|
208
|
-
if getattr(args, "remesh_mode", None):
|
|
209
|
-
G.graph["REMESH_MODE"] = str(args.remesh_mode)
|
|
210
|
-
G.graph.setdefault("GRAMMAR_CANON", DEFAULTS["GRAMMAR_CANON"]).update({"enabled": bool(args.grammar_canon)})
|
|
211
|
-
G.graph["glyph_selector"] = default_glyph_selector if args.selector == "basic" else parametric_glyph_selector
|
|
212
|
-
G.graph["GAMMA"] = {
|
|
213
|
-
"type": args.gamma_type,
|
|
214
|
-
"beta": args.gamma_beta,
|
|
215
|
-
"R0": args.gamma_R0,
|
|
216
|
-
}
|
|
217
|
-
for _ in range(int(args.steps or 200)):
|
|
218
|
-
step(G)
|
|
219
|
-
|
|
220
|
-
tg = Tg_global(G, normalize=True)
|
|
221
|
-
lat = latency_series(G)
|
|
222
|
-
rose = sigma_rose(G)
|
|
223
|
-
glifo = glifogram_series(G)
|
|
224
|
-
|
|
225
|
-
out = {
|
|
226
|
-
"Tg_global": tg,
|
|
227
|
-
"latency_mean": (sum(lat["value"]) / max(1, len(lat["value"])) ) if lat["value"] else 0.0,
|
|
228
|
-
"rose": rose,
|
|
229
|
-
"glifogram": {k: v[:10] for k, v in glifo.items()},
|
|
230
|
-
}
|
|
231
|
-
if args.save:
|
|
232
|
-
_save_json(args.save, out)
|
|
233
|
-
else:
|
|
234
|
-
print(json.dumps(out, ensure_ascii=False, indent=2))
|
|
235
|
-
return 0
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
def main(argv: Optional[List[str]] = None) -> int:
|
|
239
|
-
p = argparse.ArgumentParser(prog="tnfr")
|
|
240
|
-
sub = p.add_subparsers(dest="cmd")
|
|
241
|
-
|
|
242
|
-
p_run = sub.add_parser("run", help="Correr escenario libre o preset y opcionalmente exportar history")
|
|
243
|
-
p_run.add_argument("--nodes", type=int, default=24)
|
|
244
|
-
p_run.add_argument("--topology", choices=["ring", "complete", "erdos"], default="ring")
|
|
245
|
-
p_run.add_argument("--steps", type=int, default=200)
|
|
246
|
-
p_run.add_argument("--seed", type=int, default=1)
|
|
247
|
-
p_run.add_argument("--preset", type=str, default=None)
|
|
248
|
-
p_run.add_argument("--config", type=str, default=None)
|
|
249
|
-
p_run.add_argument("--dt", type=float, default=None)
|
|
250
|
-
p_run.add_argument("--integrator", choices=["euler", "rk4"], default=None)
|
|
251
|
-
p_run.add_argument("--save-history", dest="save_history", type=str, default=None)
|
|
252
|
-
p_run.add_argument("--export-history-base", dest="export_history_base", type=str, default=None)
|
|
253
|
-
p_run.add_argument("--export-format", dest="export_format", choices=["csv", "json"], default="json")
|
|
254
|
-
p_run.add_argument("--summary", action="store_true")
|
|
255
|
-
p_run.add_argument("--remesh-mode", choices=["knn", "mst", "community"], default=None)
|
|
256
|
-
p_run.add_argument("--no-canon", dest="grammar_canon", action="store_false", default=True, help="Desactiva gramática canónica")
|
|
257
|
-
p_run.add_argument("--grammar.enabled", dest="grammar_enabled", type=_str2bool, default=None)
|
|
258
|
-
p_run.add_argument("--grammar.zhir_requires_oz_window", dest="grammar_zhir_requires_oz_window", type=int, default=None)
|
|
259
|
-
p_run.add_argument("--grammar.zhir_dnfr_min", dest="grammar_zhir_dnfr_min", type=float, default=None)
|
|
260
|
-
p_run.add_argument("--grammar.thol_min_len", dest="grammar_thol_min_len", type=int, default=None)
|
|
261
|
-
p_run.add_argument("--grammar.thol_max_len", dest="grammar_thol_max_len", type=int, default=None)
|
|
262
|
-
p_run.add_argument("--grammar.thol_close_dnfr", dest="grammar_thol_close_dnfr", type=float, default=None)
|
|
263
|
-
p_run.add_argument("--grammar.si_high", dest="grammar_si_high", type=float, default=None)
|
|
264
|
-
p_run.add_argument("--glyph.hysteresis_window", dest="glyph_hysteresis_window", type=int, default=None)
|
|
265
|
-
p_run.add_argument("--selector", choices=["basic", "param"], default="basic")
|
|
266
|
-
p_run.add_argument("--gamma-type", choices=list(GAMMA_REGISTRY.keys()), default="none")
|
|
267
|
-
p_run.add_argument("--gamma-beta", type=float, default=0.0)
|
|
268
|
-
p_run.add_argument("--gamma-R0", type=float, default=0.0)
|
|
269
|
-
p_run.set_defaults(func=cmd_run)
|
|
270
|
-
|
|
271
|
-
p_seq = sub.add_parser("sequence", help="Ejecutar una secuencia (preset o YAML/JSON)")
|
|
272
|
-
p_seq.add_argument("--nodes", type=int, default=24)
|
|
273
|
-
p_seq.add_argument("--topology", choices=["ring", "complete", "erdos"], default="ring")
|
|
274
|
-
p_seq.add_argument("--seed", type=int, default=1)
|
|
275
|
-
p_seq.add_argument("--preset", type=str, default=None)
|
|
276
|
-
p_seq.add_argument("--sequence-file", type=str, default=None)
|
|
277
|
-
p_seq.add_argument("--config", type=str, default=None)
|
|
278
|
-
p_seq.add_argument("--dt", type=float, default=None)
|
|
279
|
-
p_seq.add_argument("--integrator", choices=["euler", "rk4"], default=None)
|
|
280
|
-
p_seq.add_argument("--save-history", dest="save_history", type=str, default=None)
|
|
281
|
-
p_seq.add_argument("--export-history-base", dest="export_history_base", type=str, default=None)
|
|
282
|
-
p_seq.add_argument("--export-format", dest="export_format", choices=["csv", "json"], default="json")
|
|
283
|
-
p_seq.add_argument("--remesh-mode", choices=["knn", "mst", "community"], default=None)
|
|
284
|
-
p_seq.add_argument("--gamma-type", choices=list(GAMMA_REGISTRY.keys()), default="none")
|
|
285
|
-
p_seq.add_argument("--gamma-beta", type=float, default=0.0)
|
|
286
|
-
p_seq.add_argument("--gamma-R0", type=float, default=0.0)
|
|
287
|
-
p_seq.add_argument("--grammar.enabled", dest="grammar_enabled", type=_str2bool, default=None)
|
|
288
|
-
p_seq.add_argument("--grammar.zhir_requires_oz_window", dest="grammar_zhir_requires_oz_window", type=int, default=None)
|
|
289
|
-
p_seq.add_argument("--grammar.zhir_dnfr_min", dest="grammar_zhir_dnfr_min", type=float, default=None)
|
|
290
|
-
p_seq.add_argument("--grammar.thol_min_len", dest="grammar_thol_min_len", type=int, default=None)
|
|
291
|
-
p_seq.add_argument("--grammar.thol_max_len", dest="grammar_thol_max_len", type=int, default=None)
|
|
292
|
-
p_seq.add_argument("--grammar.thol_close_dnfr", dest="grammar_thol_close_dnfr", type=float, default=None)
|
|
293
|
-
p_seq.add_argument("--grammar.si_high", dest="grammar_si_high", type=float, default=None)
|
|
294
|
-
p_seq.add_argument("--glyph.hysteresis_window", dest="glyph_hysteresis_window", type=int, default=None)
|
|
295
|
-
p_seq.set_defaults(func=cmd_sequence)
|
|
296
|
-
|
|
297
|
-
p_met = sub.add_parser("metrics", help="Correr breve y volcar métricas clave")
|
|
298
|
-
p_met.add_argument("--nodes", type=int, default=24)
|
|
299
|
-
p_met.add_argument("--topology", choices=["ring", "complete", "erdos"], default="ring")
|
|
300
|
-
p_met.add_argument("--steps", type=int, default=300)
|
|
301
|
-
p_met.add_argument("--seed", type=int, default=1)
|
|
302
|
-
p_met.add_argument("--dt", type=float, default=None)
|
|
303
|
-
p_met.add_argument("--integrator", choices=["euler", "rk4"], default=None)
|
|
304
|
-
p_met.add_argument("--no-canon", dest="grammar_canon", action="store_false", default=True, help="Desactiva gramática canónica")
|
|
305
|
-
p_met.add_argument("--selector", choices=["basic", "param"], default="basic")
|
|
306
|
-
p_met.add_argument("--gamma-type", choices=list(GAMMA_REGISTRY.keys()), default="none")
|
|
307
|
-
p_met.add_argument("--gamma-beta", type=float, default=0.0)
|
|
308
|
-
p_met.add_argument("--gamma-R0", type=float, default=0.0)
|
|
309
|
-
p_met.add_argument("--remesh-mode", choices=["knn", "mst", "community"], default=None)
|
|
310
|
-
p_met.add_argument("--save", type=str, default=None)
|
|
311
|
-
p_met.add_argument("--config", type=str, default=None)
|
|
312
|
-
p_met.set_defaults(func=cmd_metrics)
|
|
313
|
-
|
|
314
|
-
args = p.parse_args(argv)
|
|
315
|
-
if not hasattr(args, "func"):
|
|
316
|
-
p.print_help()
|
|
317
|
-
return 1
|
|
318
|
-
return int(args.func(args))
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
if __name__ == "__main__": # pragma: no cover
|
|
322
|
-
raise SystemExit(main())
|
tnfr/config.py
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"""Carga e inyección de configuraciones externas.
|
|
2
|
-
|
|
3
|
-
Permite definir parámetros en JSON o YAML y aplicarlos sobre ``G.graph``
|
|
4
|
-
reutilizando :func:`tnfr.constants.inject_defaults`.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
from typing import Any, Dict
|
|
9
|
-
import json
|
|
10
|
-
|
|
11
|
-
try: # pragma: no cover - dependencia opcional
|
|
12
|
-
import yaml # type: ignore
|
|
13
|
-
except Exception: # pragma: no cover
|
|
14
|
-
yaml = None
|
|
15
|
-
|
|
16
|
-
from .constants import inject_defaults
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def load_config(path: str) -> Dict[str, Any]:
|
|
20
|
-
"""Lee un archivo JSON/YAML y devuelve un ``dict`` con los parámetros."""
|
|
21
|
-
with open(path, "r", encoding="utf-8") as f:
|
|
22
|
-
text = f.read()
|
|
23
|
-
if path.endswith((".yaml", ".yml")):
|
|
24
|
-
if not yaml: # pragma: no cover - fallo en entorno sin pyyaml
|
|
25
|
-
raise RuntimeError("pyyaml no está instalado")
|
|
26
|
-
data = yaml.safe_load(text)
|
|
27
|
-
else:
|
|
28
|
-
data = json.loads(text)
|
|
29
|
-
if not isinstance(data, dict):
|
|
30
|
-
raise ValueError("El archivo de configuración debe contener un objeto")
|
|
31
|
-
return data
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def apply_config(G, path: str) -> None:
|
|
35
|
-
"""Inyecta parámetros desde ``path`` sobre ``G.graph``.
|
|
36
|
-
|
|
37
|
-
Se reutiliza :func:`inject_defaults` para mantener la semántica de los
|
|
38
|
-
*defaults* canónicos.
|
|
39
|
-
"""
|
|
40
|
-
cfg = load_config(path)
|
|
41
|
-
inject_defaults(G, cfg, override=True)
|
tnfr/constants.py
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
constants.py — TNFR canónica
|
|
3
|
-
|
|
4
|
-
Centraliza parámetros por defecto y nombres que usan el resto de módulos.
|
|
5
|
-
Provee utilidades para inyectarlos en G.graph.
|
|
6
|
-
"""
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
from typing import Dict, Any
|
|
9
|
-
|
|
10
|
-
# -------------------------
|
|
11
|
-
# Parámetros canónicos
|
|
12
|
-
# -------------------------
|
|
13
|
-
DEFAULTS: Dict[str, Any] = {
|
|
14
|
-
# Discretización
|
|
15
|
-
"DT": 1.0,
|
|
16
|
-
"INTEGRATOR_METHOD": "euler",
|
|
17
|
-
"DT_MIN": 0.1,
|
|
18
|
-
|
|
19
|
-
# Rango de EPI (estructura primaria)
|
|
20
|
-
"EPI_MIN": -1.0,
|
|
21
|
-
"EPI_MAX": 1.0,
|
|
22
|
-
# Alias histórico usado por algunos proyectos
|
|
23
|
-
"EPI_MAX_GLOBAL": 1.0,
|
|
24
|
-
|
|
25
|
-
# Rango de frecuencia estructural νf
|
|
26
|
-
"VF_MIN": 0.0,
|
|
27
|
-
"VF_MAX": 1.0,
|
|
28
|
-
|
|
29
|
-
# Envolvente de fase
|
|
30
|
-
"THETA_WRAP": True,
|
|
31
|
-
|
|
32
|
-
# --- Inicialización (evitar simetrías) ---
|
|
33
|
-
"INIT_RANDOM_PHASE": True, # si True, θ ~ U[-π, π]
|
|
34
|
-
"INIT_THETA_MIN": -3.141592653589793,
|
|
35
|
-
"INIT_THETA_MAX": 3.141592653589793,
|
|
36
|
-
|
|
37
|
-
"INIT_VF_MODE": "uniform", # "uniform" | "normal"
|
|
38
|
-
# para uniform:
|
|
39
|
-
"INIT_VF_MIN": None, # si None → usa VF_MIN
|
|
40
|
-
"INIT_VF_MAX": None, # si None → usa VF_MAX
|
|
41
|
-
# para normal:
|
|
42
|
-
"INIT_VF_MEAN": 0.5,
|
|
43
|
-
"INIT_VF_STD": 0.15,
|
|
44
|
-
# clamp de νf a límites canónicos
|
|
45
|
-
"INIT_VF_CLAMP_TO_LIMITS": True,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# Mezcla para ΔNFR (campo nodal)
|
|
49
|
-
# phase: dispersión de fase local; epi: gradiente de EPI; vf: desajuste de νf;
|
|
50
|
-
# topo: término topológico (p. ej., centralidad). Pesos se normalizan.
|
|
51
|
-
"DNFR_WEIGHTS": {"phase": 0.34, "epi": 0.33, "vf": 0.33, "topo": 0.0},
|
|
52
|
-
|
|
53
|
-
# Índice de sentido Si = α·νf_norm + β·(1 - disp_fase) + γ·(1 - |ΔNFR|/max)
|
|
54
|
-
"SI_WEIGHTS": {"alpha": 0.34, "beta": 0.33, "gamma": 0.33},
|
|
55
|
-
|
|
56
|
-
# Coordinación de fase (U’M) global/vecinal por paso
|
|
57
|
-
"PHASE_K_GLOBAL": 0.05,
|
|
58
|
-
"PHASE_K_LOCAL": 0.15,
|
|
59
|
-
|
|
60
|
-
# Coordinación de fase adaptativa (kG/kL dinámicos por estado)
|
|
61
|
-
"PHASE_ADAPT": {
|
|
62
|
-
"enabled": True, # activar adaptación automática si no se pasan fuerzas explícitas a la función
|
|
63
|
-
"R_hi": 0.90, # sincronía alta (Kuramoto R) => estado ESTABLE
|
|
64
|
-
"R_lo": 0.60, # sincronía baja => estado DISONANTE
|
|
65
|
-
"disr_hi": 0.50, # carga glífica disruptiva alta => DISONANTE
|
|
66
|
-
"disr_lo": 0.25, # carga glífica disruptiva baja + R alta => ESTABLE
|
|
67
|
-
"kG_min": 0.01, "kG_max": 0.20,
|
|
68
|
-
"kL_min": 0.05, "kL_max": 0.25,
|
|
69
|
-
"up": 0.10, # velocidad de subida hacia el objetivo
|
|
70
|
-
"down": 0.07 # velocidad de bajada hacia el objetivo
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
"STOP_EARLY": {"enabled": False, "window": 25, "fraction": 0.90},
|
|
74
|
-
|
|
75
|
-
# Criterios de estabilidad (para activar RE’MESH de red)
|
|
76
|
-
"EPS_DNFR_STABLE": 1e-3,
|
|
77
|
-
"EPS_DEPI_STABLE": 1e-3,
|
|
78
|
-
"FRACTION_STABLE_REMESH": 0.80, # fracción de nodos estables requerida
|
|
79
|
-
"REMESH_COOLDOWN_VENTANA": 20, # pasos mínimos entre RE’MESH
|
|
80
|
-
"REMESH_COOLDOWN_TS": 0.0, # cooldown adicional por tiempo simulado
|
|
81
|
-
# Gating adicional basado en observadores (conmutador + ventana)
|
|
82
|
-
"REMESH_REQUIRE_STABILITY": True, # si True, exige ventana de estabilidad multi-métrica
|
|
83
|
-
"REMESH_STABILITY_WINDOW": 25, # tamaño de ventana para evaluar estabilidad
|
|
84
|
-
"REMESH_MIN_PHASE_SYNC": 0.85, # media mínima de sincronía de fase en ventana
|
|
85
|
-
"REMESH_MAX_GLYPH_DISR": 0.35, # media máxima de carga glífica disruptiva en ventana
|
|
86
|
-
"REMESH_MIN_SIGMA_MAG": 0.50, # magnitud mínima de σ en ventana
|
|
87
|
-
"REMESH_MIN_KURAMOTO_R": 0.80, # R de Kuramoto mínimo en ventana
|
|
88
|
-
"REMESH_MIN_SI_HI_FRAC": 0.50, # fracción mínima de nodos con Si alto
|
|
89
|
-
"REMESH_LOG_EVENTS": True, # guarda eventos y metadatos del RE’MESH
|
|
90
|
-
"REMESH_MODE": "knn", # modo de remallado topológico
|
|
91
|
-
"REMESH_COMMUNITY_K": 2, # conexiones por comunidad
|
|
92
|
-
|
|
93
|
-
# RE’MESH: memoria τ y mezcla α (global/local)
|
|
94
|
-
"REMESH_TAU": 8, # compatibilidad: tau global por defecto
|
|
95
|
-
"REMESH_TAU_GLOBAL": 8, # pasos hacia atrás (escala global)
|
|
96
|
-
"REMESH_TAU_LOCAL": 4, # pasos hacia atrás (escala local)
|
|
97
|
-
"REMESH_ALPHA": 0.5, # mezcla con pasado
|
|
98
|
-
"REMESH_ALPHA_HARD": False, # si True ignora GLYPH_FACTORS['REMESH_alpha']
|
|
99
|
-
|
|
100
|
-
# Soporte y norma de la EPI
|
|
101
|
-
"EPI_SUPPORT_THR": 0.05, # umbral para Supp(EPI)
|
|
102
|
-
|
|
103
|
-
# U'M — compatibilidad mínima para crear/reforzar enlaces funcionales
|
|
104
|
-
"UM_COMPAT_THRESHOLD": 0.75,
|
|
105
|
-
|
|
106
|
-
# Histéresis glífica
|
|
107
|
-
"GLYPH_HYSTERESIS_WINDOW": 7,
|
|
108
|
-
|
|
109
|
-
# Lags máximos sin emisión (A’L) y recepción (E’N)
|
|
110
|
-
"AL_MAX_LAG": 5,
|
|
111
|
-
"EN_MAX_LAG": 3,
|
|
112
|
-
|
|
113
|
-
# Margen de histéresis del selector (cuánto "aguanta" sin cambiar glifo si está cerca de un umbral)
|
|
114
|
-
"GLYPH_SELECTOR_MARGIN": 0.05,
|
|
115
|
-
|
|
116
|
-
# Ventana para estimar la carga glífica en history/plots
|
|
117
|
-
"GLYPH_LOAD_WINDOW": 50,
|
|
118
|
-
|
|
119
|
-
# Tamaño de ventana para coherencia promedio W̄
|
|
120
|
-
"WBAR_WINDOW": 25,
|
|
121
|
-
|
|
122
|
-
# Adaptación de frecuencia estructural por coherencia
|
|
123
|
-
"VF_ADAPT_TAU": 5, # pasos estables antes de ajustar νf
|
|
124
|
-
"VF_ADAPT_MU": 0.1, # velocidad de ajuste hacia la media vecinal
|
|
125
|
-
|
|
126
|
-
# Factores suaves por glifo (operadores)
|
|
127
|
-
"GLYPH_FACTORS": {
|
|
128
|
-
"AL_boost": 0.05, # A’L — pequeña emisión
|
|
129
|
-
"EN_mix": 0.25, # E’N — mezcla con vecindad
|
|
130
|
-
"IL_dnfr_factor": 0.7, # I’L — reduce ΔNFR
|
|
131
|
-
"OZ_dnfr_factor": 1.3, # O’Z — aumenta ΔNFR
|
|
132
|
-
"UM_theta_push": 0.25, # U’M — empuje adicional de fase local
|
|
133
|
-
"RA_epi_diff": 0.15, # R’A — difusión EPI
|
|
134
|
-
"SHA_vf_factor": 0.85, # SH’A — baja νf
|
|
135
|
-
"VAL_scale": 1.15, # VA’L — expande EPI
|
|
136
|
-
"NUL_scale": 0.85, # NU’L — contrae EPI
|
|
137
|
-
"THOL_accel": 0.10, # T’HOL — acelera (seg. deriv.) si hay umbral
|
|
138
|
-
"ZHIR_theta_shift": 1.57079632679, # Z’HIR — desplazamiento ~π/2
|
|
139
|
-
"NAV_jitter": 0.05, # NA’V — pequeña inestabilidad creativa
|
|
140
|
-
"NAV_eta": 0.5, # NA’V — peso de convergencia hacia νf
|
|
141
|
-
"REMESH_alpha": 0.5, # RE’MESH — mezcla si no se usa REMESH_ALPHA
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
# Umbrales para el selector glífico por defecto
|
|
145
|
-
"GLYPH_THRESHOLDS": {"hi": 0.66, "lo": 0.33, "dnfr": 1e-3},
|
|
146
|
-
|
|
147
|
-
# Comportamiento NA’V
|
|
148
|
-
"NAV_RANDOM": True, # si True, usa jitter aleatorio en [-j, j]; si False, jitter determinista por signo
|
|
149
|
-
"NAV_STRICT": False, # si True, fuerza ΔNFR ← νf (sin mezcla)
|
|
150
|
-
"RANDOM_SEED": 0, # semilla base para reproducibilidad del jitter
|
|
151
|
-
|
|
152
|
-
# Modo ruido para O’Z
|
|
153
|
-
"OZ_NOISE_MODE": False, # si True, añade ruido aditivo en ΔNFR
|
|
154
|
-
"OZ_SIGMA": 0.1, # amplitud del ruido uniforme [-σ, σ]
|
|
155
|
-
|
|
156
|
-
# Gramática glífica (suave): evita repetir ciertos glifos salvo que el campo lo exija
|
|
157
|
-
"GRAMMAR": {
|
|
158
|
-
"window": 3, # cuántos pasos recientes miramos por nodo
|
|
159
|
-
"avoid_repeats": ["Z’HIR", "O’Z", "T’HOL"],
|
|
160
|
-
"force_dnfr": 0.60, # si |ΔNFR|_norm ≥ este valor, se permite repetir
|
|
161
|
-
"force_accel": 0.60, # o si |accel|_norm ≥ este valor
|
|
162
|
-
"fallbacks": { # a qué glifo caer si se bloquea el candidato
|
|
163
|
-
"Z’HIR": "NA’V",
|
|
164
|
-
"O’Z": "Z’HIR",
|
|
165
|
-
"T’HOL": "NA’V"
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
|
|
169
|
-
# --- Selector multiobjetivo ---
|
|
170
|
-
# Ponderaciones (se reescalan a 1 automáticamente)
|
|
171
|
-
"SELECTOR_WEIGHTS": {"w_si": 0.5, "w_dnfr": 0.3, "w_accel": 0.2},
|
|
172
|
-
# Umbrales hi/lo para decidir categorías (trabajan con |ΔNFR|_norm y |accel|_norm)
|
|
173
|
-
"SELECTOR_THRESHOLDS": {
|
|
174
|
-
"si_hi": 0.66, "si_lo": 0.33,
|
|
175
|
-
"dnfr_hi": 0.50, "dnfr_lo": 0.10,
|
|
176
|
-
"accel_hi": 0.50, "accel_lo": 0.10
|
|
177
|
-
},
|
|
178
|
-
# Callbacks Γ(R)
|
|
179
|
-
"GAMMA": {
|
|
180
|
-
"type": "none", # 'none' | 'kuramoto_linear' | 'kuramoto_bandpass'
|
|
181
|
-
"beta": 0.0,
|
|
182
|
-
"R0": 0.0,
|
|
183
|
-
},
|
|
184
|
-
"CALLBACKS_STRICT": False, # si True, un error en callback detiene; si False, se loguea y continúa
|
|
185
|
-
"VALIDATORS_STRICT": False, # si True, alerta si se clampa fuera de rango
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
# Gramática glífica canónica
|
|
189
|
-
DEFAULTS.setdefault("GRAMMAR_CANON", {
|
|
190
|
-
"enabled": True, # activar la gramática canónica
|
|
191
|
-
"zhir_requires_oz_window": 3, # cuántos pasos atrás buscamos O’Z
|
|
192
|
-
"zhir_dnfr_min": 0.05, # si |ΔNFR|_norm < este valor, no permitimos Z’HIR sin O’Z
|
|
193
|
-
"thol_min_len": 2,
|
|
194
|
-
"thol_max_len": 6,
|
|
195
|
-
"thol_close_dnfr": 0.15, # si el campo calma, cerramos con SH’A/NU’L
|
|
196
|
-
"si_high": 0.66, # umbral para elegir NU’L vs SH’A al cerrar
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
# --- Coherencia (W) ---
|
|
200
|
-
DEFAULTS.setdefault("COHERENCE", {
|
|
201
|
-
"enabled": True,
|
|
202
|
-
"scope": "neighbors", # "neighbors" | "all"
|
|
203
|
-
"weights": {
|
|
204
|
-
"phase": 0.34,
|
|
205
|
-
"epi": 0.33,
|
|
206
|
-
"vf": 0.20,
|
|
207
|
-
"si": 0.13,
|
|
208
|
-
},
|
|
209
|
-
"self_on_diag": True, # W_ii = 1.0
|
|
210
|
-
"store_mode": "sparse", # "sparse" | "dense"
|
|
211
|
-
"threshold": 0.0,
|
|
212
|
-
"history_key": "W_sparse",
|
|
213
|
-
"Wi_history_key": "W_i",
|
|
214
|
-
"stats_history_key": "W_stats",
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
# --- Diagnóstico nodal ---
|
|
218
|
-
DEFAULTS.setdefault("DIAGNOSIS", {
|
|
219
|
-
"enabled": True,
|
|
220
|
-
"window": 16,
|
|
221
|
-
"history_key": "nodal_diag",
|
|
222
|
-
"stable": {"Rloc_hi": 0.80, "dnfr_lo": 0.20, "persist": 3},
|
|
223
|
-
"dissonance": {"Rloc_lo": 0.40, "dnfr_hi": 0.50, "persist": 3},
|
|
224
|
-
"transition": {"persist": 2},
|
|
225
|
-
"compute_symmetry": True,
|
|
226
|
-
"include_typology": False,
|
|
227
|
-
"advice": {
|
|
228
|
-
"stable": ["Coherencia", "Acoplamiento", "Resonancia"],
|
|
229
|
-
"transition": ["Transición", "Resonancia", "Autoorganización"],
|
|
230
|
-
"dissonant": ["Silencio", "Contracción", "Mutación"],
|
|
231
|
-
},
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
# -------------------------
|
|
236
|
-
# Utilidades
|
|
237
|
-
# -------------------------
|
|
238
|
-
|
|
239
|
-
def attach_defaults(G, override: bool = False) -> None:
|
|
240
|
-
"""Escribe DEFAULTS en G.graph (sin sobreescribir si override=False)."""
|
|
241
|
-
inject_defaults(G, DEFAULTS, override=override)
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
def inject_defaults(G, defaults: Dict[str, Any] = DEFAULTS, override: bool = False) -> None:
|
|
245
|
-
"""Alias de conveniencia para inyectar ``DEFAULTS`` en ``G.graph``.
|
|
246
|
-
|
|
247
|
-
Permite pasar un diccionario de *defaults* alternativo y mantiene la
|
|
248
|
-
semántica de ``attach_defaults`` existente. Si ``override`` es ``True`` se
|
|
249
|
-
sobreescriben valores ya presentes.
|
|
250
|
-
"""
|
|
251
|
-
G.graph.setdefault("_tnfr_defaults_attached", False)
|
|
252
|
-
for k, v in defaults.items():
|
|
253
|
-
if override or k not in G.graph:
|
|
254
|
-
G.graph[k] = v
|
|
255
|
-
G.graph["_tnfr_defaults_attached"] = True
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
def merge_overrides(G, **overrides) -> None:
|
|
259
|
-
"""Aplica cambios puntuales a G.graph.
|
|
260
|
-
Útil para ajustar pesos sin tocar DEFAULTS globales.
|
|
261
|
-
"""
|
|
262
|
-
for k, v in overrides.items():
|
|
263
|
-
G.graph[k] = v
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
# Alias exportados por conveniencia (evita imports circulares)
|
|
267
|
-
ALIAS_VF = ("νf", "nu_f", "nu-f", "nu", "freq", "frequency")
|
|
268
|
-
ALIAS_THETA = ("θ", "theta", "fase", "phi", "phase")
|
|
269
|
-
ALIAS_DNFR = ("ΔNFR", "delta_nfr", "dnfr")
|
|
270
|
-
ALIAS_EPI = ("EPI", "psi", "PSI", "value")
|
|
271
|
-
ALIAS_EPI_KIND = ("EPI_kind", "epi_kind", "source_glifo")
|
|
272
|
-
ALIAS_SI = ("Si", "sense_index", "S_i", "sense", "meaning_index")
|
|
273
|
-
ALIAS_dEPI = ("dEPI_dt", "dpsi_dt", "dEPI", "velocity")
|
|
274
|
-
ALIAS_D2EPI = ("d2EPI_dt2", "d2psi_dt2", "d2EPI", "accel")
|
|
275
|
-
ALIAS_dVF = ("dνf_dt", "dvf_dt", "dnu_dt", "dvf")
|
|
276
|
-
ALIAS_D2VF = ("d2νf_dt2", "d2vf_dt2", "d2nu_dt2", "B")
|
|
277
|
-
ALIAS_dSI = ("δSi", "delta_Si", "dSi")
|