tnfr 3.0.3__py3-none-any.whl → 8.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tnfr might be problematic. Click here for more details.
- tnfr/__init__.py +375 -56
- tnfr/__init__.pyi +33 -0
- tnfr/_compat.py +10 -0
- tnfr/_generated_version.py +34 -0
- tnfr/_version.py +49 -0
- tnfr/_version.pyi +7 -0
- tnfr/alias.py +723 -0
- tnfr/alias.pyi +108 -0
- tnfr/backends/__init__.py +354 -0
- tnfr/backends/jax_backend.py +173 -0
- tnfr/backends/numpy_backend.py +238 -0
- tnfr/backends/optimized_numpy.py +420 -0
- tnfr/backends/torch_backend.py +408 -0
- tnfr/cache.py +171 -0
- tnfr/cache.pyi +13 -0
- tnfr/cli/__init__.py +110 -0
- tnfr/cli/__init__.pyi +26 -0
- tnfr/cli/arguments.py +489 -0
- tnfr/cli/arguments.pyi +29 -0
- tnfr/cli/execution.py +914 -0
- tnfr/cli/execution.pyi +70 -0
- tnfr/cli/interactive_validator.py +614 -0
- tnfr/cli/utils.py +51 -0
- tnfr/cli/utils.pyi +7 -0
- tnfr/cli/validate.py +236 -0
- tnfr/compat/__init__.py +85 -0
- tnfr/compat/dataclass.py +136 -0
- tnfr/compat/jsonschema_stub.py +61 -0
- tnfr/compat/matplotlib_stub.py +73 -0
- tnfr/compat/numpy_stub.py +155 -0
- tnfr/config/__init__.py +224 -0
- tnfr/config/__init__.pyi +10 -0
- tnfr/config/constants.py +104 -0
- tnfr/config/constants.pyi +12 -0
- tnfr/config/defaults.py +54 -0
- tnfr/config/defaults_core.py +212 -0
- tnfr/config/defaults_init.py +33 -0
- tnfr/config/defaults_metric.py +104 -0
- tnfr/config/feature_flags.py +81 -0
- tnfr/config/feature_flags.pyi +16 -0
- tnfr/config/glyph_constants.py +31 -0
- tnfr/config/init.py +77 -0
- tnfr/config/init.pyi +8 -0
- tnfr/config/operator_names.py +254 -0
- tnfr/config/operator_names.pyi +36 -0
- tnfr/config/physics_derivation.py +354 -0
- tnfr/config/presets.py +83 -0
- tnfr/config/presets.pyi +7 -0
- tnfr/config/security.py +927 -0
- tnfr/config/thresholds.py +114 -0
- tnfr/config/tnfr_config.py +498 -0
- tnfr/constants/__init__.py +92 -0
- tnfr/constants/__init__.pyi +92 -0
- tnfr/constants/aliases.py +33 -0
- tnfr/constants/aliases.pyi +27 -0
- tnfr/constants/init.py +33 -0
- tnfr/constants/init.pyi +12 -0
- tnfr/constants/metric.py +104 -0
- tnfr/constants/metric.pyi +19 -0
- tnfr/core/__init__.py +33 -0
- tnfr/core/container.py +226 -0
- tnfr/core/default_implementations.py +329 -0
- tnfr/core/interfaces.py +279 -0
- tnfr/dynamics/__init__.py +238 -0
- tnfr/dynamics/__init__.pyi +83 -0
- tnfr/dynamics/adaptation.py +267 -0
- tnfr/dynamics/adaptation.pyi +7 -0
- tnfr/dynamics/adaptive_sequences.py +189 -0
- tnfr/dynamics/adaptive_sequences.pyi +14 -0
- tnfr/dynamics/aliases.py +23 -0
- tnfr/dynamics/aliases.pyi +19 -0
- tnfr/dynamics/bifurcation.py +232 -0
- tnfr/dynamics/canonical.py +229 -0
- tnfr/dynamics/canonical.pyi +48 -0
- tnfr/dynamics/coordination.py +385 -0
- tnfr/dynamics/coordination.pyi +25 -0
- tnfr/dynamics/dnfr.py +3034 -0
- tnfr/dynamics/dnfr.pyi +26 -0
- tnfr/dynamics/dynamic_limits.py +225 -0
- tnfr/dynamics/feedback.py +252 -0
- tnfr/dynamics/feedback.pyi +24 -0
- tnfr/dynamics/fused_dnfr.py +454 -0
- tnfr/dynamics/homeostasis.py +157 -0
- tnfr/dynamics/homeostasis.pyi +14 -0
- tnfr/dynamics/integrators.py +661 -0
- tnfr/dynamics/integrators.pyi +36 -0
- tnfr/dynamics/learning.py +310 -0
- tnfr/dynamics/learning.pyi +33 -0
- tnfr/dynamics/metabolism.py +254 -0
- tnfr/dynamics/nbody.py +796 -0
- tnfr/dynamics/nbody_tnfr.py +783 -0
- tnfr/dynamics/propagation.py +326 -0
- tnfr/dynamics/runtime.py +908 -0
- tnfr/dynamics/runtime.pyi +77 -0
- tnfr/dynamics/sampling.py +36 -0
- tnfr/dynamics/sampling.pyi +7 -0
- tnfr/dynamics/selectors.py +711 -0
- tnfr/dynamics/selectors.pyi +85 -0
- tnfr/dynamics/structural_clip.py +207 -0
- tnfr/errors/__init__.py +37 -0
- tnfr/errors/contextual.py +492 -0
- tnfr/execution.py +223 -0
- tnfr/execution.pyi +45 -0
- tnfr/extensions/__init__.py +205 -0
- tnfr/extensions/__init__.pyi +18 -0
- tnfr/extensions/base.py +173 -0
- tnfr/extensions/base.pyi +35 -0
- tnfr/extensions/business/__init__.py +71 -0
- tnfr/extensions/business/__init__.pyi +11 -0
- tnfr/extensions/business/cookbook.py +88 -0
- tnfr/extensions/business/cookbook.pyi +8 -0
- tnfr/extensions/business/health_analyzers.py +202 -0
- tnfr/extensions/business/health_analyzers.pyi +9 -0
- tnfr/extensions/business/patterns.py +183 -0
- tnfr/extensions/business/patterns.pyi +8 -0
- tnfr/extensions/medical/__init__.py +73 -0
- tnfr/extensions/medical/__init__.pyi +11 -0
- tnfr/extensions/medical/cookbook.py +88 -0
- tnfr/extensions/medical/cookbook.pyi +8 -0
- tnfr/extensions/medical/health_analyzers.py +181 -0
- tnfr/extensions/medical/health_analyzers.pyi +9 -0
- tnfr/extensions/medical/patterns.py +163 -0
- tnfr/extensions/medical/patterns.pyi +8 -0
- tnfr/flatten.py +262 -0
- tnfr/flatten.pyi +21 -0
- tnfr/gamma.py +354 -0
- tnfr/gamma.pyi +36 -0
- tnfr/glyph_history.py +377 -0
- tnfr/glyph_history.pyi +35 -0
- tnfr/glyph_runtime.py +19 -0
- tnfr/glyph_runtime.pyi +8 -0
- tnfr/immutable.py +218 -0
- tnfr/immutable.pyi +36 -0
- tnfr/initialization.py +203 -0
- tnfr/initialization.pyi +65 -0
- tnfr/io.py +10 -0
- tnfr/io.pyi +13 -0
- tnfr/locking.py +37 -0
- tnfr/locking.pyi +7 -0
- tnfr/mathematics/__init__.py +79 -0
- tnfr/mathematics/backend.py +453 -0
- tnfr/mathematics/backend.pyi +99 -0
- tnfr/mathematics/dynamics.py +408 -0
- tnfr/mathematics/dynamics.pyi +90 -0
- tnfr/mathematics/epi.py +391 -0
- tnfr/mathematics/epi.pyi +65 -0
- tnfr/mathematics/generators.py +242 -0
- tnfr/mathematics/generators.pyi +29 -0
- tnfr/mathematics/metrics.py +119 -0
- tnfr/mathematics/metrics.pyi +16 -0
- tnfr/mathematics/operators.py +239 -0
- tnfr/mathematics/operators.pyi +59 -0
- tnfr/mathematics/operators_factory.py +124 -0
- tnfr/mathematics/operators_factory.pyi +11 -0
- tnfr/mathematics/projection.py +87 -0
- tnfr/mathematics/projection.pyi +33 -0
- tnfr/mathematics/runtime.py +182 -0
- tnfr/mathematics/runtime.pyi +64 -0
- tnfr/mathematics/spaces.py +256 -0
- tnfr/mathematics/spaces.pyi +83 -0
- tnfr/mathematics/transforms.py +305 -0
- tnfr/mathematics/transforms.pyi +62 -0
- tnfr/metrics/__init__.py +79 -0
- tnfr/metrics/__init__.pyi +20 -0
- tnfr/metrics/buffer_cache.py +163 -0
- tnfr/metrics/buffer_cache.pyi +24 -0
- tnfr/metrics/cache_utils.py +214 -0
- tnfr/metrics/coherence.py +2009 -0
- tnfr/metrics/coherence.pyi +129 -0
- tnfr/metrics/common.py +158 -0
- tnfr/metrics/common.pyi +35 -0
- tnfr/metrics/core.py +316 -0
- tnfr/metrics/core.pyi +13 -0
- tnfr/metrics/diagnosis.py +833 -0
- tnfr/metrics/diagnosis.pyi +86 -0
- tnfr/metrics/emergence.py +245 -0
- tnfr/metrics/export.py +179 -0
- tnfr/metrics/export.pyi +7 -0
- tnfr/metrics/glyph_timing.py +379 -0
- tnfr/metrics/glyph_timing.pyi +81 -0
- tnfr/metrics/learning_metrics.py +280 -0
- tnfr/metrics/learning_metrics.pyi +21 -0
- tnfr/metrics/phase_coherence.py +351 -0
- tnfr/metrics/phase_compatibility.py +349 -0
- tnfr/metrics/reporting.py +183 -0
- tnfr/metrics/reporting.pyi +25 -0
- tnfr/metrics/sense_index.py +1203 -0
- tnfr/metrics/sense_index.pyi +9 -0
- tnfr/metrics/trig.py +373 -0
- tnfr/metrics/trig.pyi +13 -0
- tnfr/metrics/trig_cache.py +233 -0
- tnfr/metrics/trig_cache.pyi +10 -0
- tnfr/multiscale/__init__.py +32 -0
- tnfr/multiscale/hierarchical.py +517 -0
- tnfr/node.py +763 -0
- tnfr/node.pyi +139 -0
- tnfr/observers.py +255 -130
- tnfr/observers.pyi +31 -0
- tnfr/ontosim.py +144 -137
- tnfr/ontosim.pyi +28 -0
- tnfr/operators/__init__.py +1672 -0
- tnfr/operators/__init__.pyi +31 -0
- tnfr/operators/algebra.py +277 -0
- tnfr/operators/canonical_patterns.py +420 -0
- tnfr/operators/cascade.py +267 -0
- tnfr/operators/cycle_detection.py +358 -0
- tnfr/operators/definitions.py +4108 -0
- tnfr/operators/definitions.pyi +78 -0
- tnfr/operators/grammar.py +1164 -0
- tnfr/operators/grammar.pyi +140 -0
- tnfr/operators/hamiltonian.py +710 -0
- tnfr/operators/health_analyzer.py +809 -0
- tnfr/operators/jitter.py +272 -0
- tnfr/operators/jitter.pyi +11 -0
- tnfr/operators/lifecycle.py +314 -0
- tnfr/operators/metabolism.py +618 -0
- tnfr/operators/metrics.py +2138 -0
- tnfr/operators/network_analysis/__init__.py +27 -0
- tnfr/operators/network_analysis/source_detection.py +186 -0
- tnfr/operators/nodal_equation.py +395 -0
- tnfr/operators/pattern_detection.py +660 -0
- tnfr/operators/patterns.py +669 -0
- tnfr/operators/postconditions/__init__.py +38 -0
- tnfr/operators/postconditions/mutation.py +236 -0
- tnfr/operators/preconditions/__init__.py +1226 -0
- tnfr/operators/preconditions/coherence.py +305 -0
- tnfr/operators/preconditions/dissonance.py +236 -0
- tnfr/operators/preconditions/emission.py +128 -0
- tnfr/operators/preconditions/mutation.py +580 -0
- tnfr/operators/preconditions/reception.py +125 -0
- tnfr/operators/preconditions/resonance.py +364 -0
- tnfr/operators/registry.py +74 -0
- tnfr/operators/registry.pyi +9 -0
- tnfr/operators/remesh.py +1809 -0
- tnfr/operators/remesh.pyi +26 -0
- tnfr/operators/structural_units.py +268 -0
- tnfr/operators/unified_grammar.py +105 -0
- tnfr/parallel/__init__.py +54 -0
- tnfr/parallel/auto_scaler.py +234 -0
- tnfr/parallel/distributed.py +384 -0
- tnfr/parallel/engine.py +238 -0
- tnfr/parallel/gpu_engine.py +420 -0
- tnfr/parallel/monitoring.py +248 -0
- tnfr/parallel/partitioner.py +459 -0
- tnfr/py.typed +0 -0
- tnfr/recipes/__init__.py +22 -0
- tnfr/recipes/cookbook.py +743 -0
- tnfr/rng.py +178 -0
- tnfr/rng.pyi +26 -0
- tnfr/schemas/__init__.py +8 -0
- tnfr/schemas/grammar.json +94 -0
- tnfr/sdk/__init__.py +107 -0
- tnfr/sdk/__init__.pyi +19 -0
- tnfr/sdk/adaptive_system.py +173 -0
- tnfr/sdk/adaptive_system.pyi +21 -0
- tnfr/sdk/builders.py +370 -0
- tnfr/sdk/builders.pyi +51 -0
- tnfr/sdk/fluent.py +1121 -0
- tnfr/sdk/fluent.pyi +74 -0
- tnfr/sdk/templates.py +342 -0
- tnfr/sdk/templates.pyi +41 -0
- tnfr/sdk/utils.py +341 -0
- tnfr/secure_config.py +46 -0
- tnfr/security/__init__.py +70 -0
- tnfr/security/database.py +514 -0
- tnfr/security/subprocess.py +503 -0
- tnfr/security/validation.py +290 -0
- tnfr/selector.py +247 -0
- tnfr/selector.pyi +19 -0
- tnfr/sense.py +378 -0
- tnfr/sense.pyi +23 -0
- tnfr/services/__init__.py +17 -0
- tnfr/services/orchestrator.py +325 -0
- tnfr/sparse/__init__.py +39 -0
- tnfr/sparse/representations.py +492 -0
- tnfr/structural.py +705 -0
- tnfr/structural.pyi +83 -0
- tnfr/telemetry/__init__.py +35 -0
- tnfr/telemetry/cache_metrics.py +226 -0
- tnfr/telemetry/cache_metrics.pyi +64 -0
- tnfr/telemetry/nu_f.py +422 -0
- tnfr/telemetry/nu_f.pyi +108 -0
- tnfr/telemetry/verbosity.py +36 -0
- tnfr/telemetry/verbosity.pyi +15 -0
- tnfr/tokens.py +58 -0
- tnfr/tokens.pyi +36 -0
- tnfr/tools/__init__.py +20 -0
- tnfr/tools/domain_templates.py +478 -0
- tnfr/tools/sequence_generator.py +846 -0
- tnfr/topology/__init__.py +13 -0
- tnfr/topology/asymmetry.py +151 -0
- tnfr/trace.py +543 -0
- tnfr/trace.pyi +42 -0
- tnfr/tutorials/__init__.py +38 -0
- tnfr/tutorials/autonomous_evolution.py +285 -0
- tnfr/tutorials/interactive.py +1576 -0
- tnfr/tutorials/structural_metabolism.py +238 -0
- tnfr/types.py +775 -0
- tnfr/types.pyi +357 -0
- tnfr/units.py +68 -0
- tnfr/units.pyi +13 -0
- tnfr/utils/__init__.py +282 -0
- tnfr/utils/__init__.pyi +215 -0
- tnfr/utils/cache.py +4223 -0
- tnfr/utils/cache.pyi +470 -0
- tnfr/utils/callbacks.py +375 -0
- tnfr/utils/callbacks.pyi +49 -0
- tnfr/utils/chunks.py +108 -0
- tnfr/utils/chunks.pyi +22 -0
- tnfr/utils/data.py +428 -0
- tnfr/utils/data.pyi +74 -0
- tnfr/utils/graph.py +85 -0
- tnfr/utils/graph.pyi +10 -0
- tnfr/utils/init.py +821 -0
- tnfr/utils/init.pyi +80 -0
- tnfr/utils/io.py +559 -0
- tnfr/utils/io.pyi +66 -0
- tnfr/utils/numeric.py +114 -0
- tnfr/utils/numeric.pyi +21 -0
- tnfr/validation/__init__.py +257 -0
- tnfr/validation/__init__.pyi +85 -0
- tnfr/validation/compatibility.py +460 -0
- tnfr/validation/compatibility.pyi +6 -0
- tnfr/validation/config.py +73 -0
- tnfr/validation/graph.py +139 -0
- tnfr/validation/graph.pyi +18 -0
- tnfr/validation/input_validation.py +755 -0
- tnfr/validation/invariants.py +712 -0
- tnfr/validation/rules.py +253 -0
- tnfr/validation/rules.pyi +44 -0
- tnfr/validation/runtime.py +279 -0
- tnfr/validation/runtime.pyi +28 -0
- tnfr/validation/sequence_validator.py +162 -0
- tnfr/validation/soft_filters.py +170 -0
- tnfr/validation/soft_filters.pyi +32 -0
- tnfr/validation/spectral.py +164 -0
- tnfr/validation/spectral.pyi +42 -0
- tnfr/validation/validator.py +1266 -0
- tnfr/validation/window.py +39 -0
- tnfr/validation/window.pyi +1 -0
- tnfr/visualization/__init__.py +98 -0
- tnfr/visualization/cascade_viz.py +256 -0
- tnfr/visualization/hierarchy.py +284 -0
- tnfr/visualization/sequence_plotter.py +784 -0
- tnfr/viz/__init__.py +60 -0
- tnfr/viz/matplotlib.py +278 -0
- tnfr/viz/matplotlib.pyi +35 -0
- tnfr-8.5.0.dist-info/METADATA +573 -0
- tnfr-8.5.0.dist-info/RECORD +353 -0
- tnfr-8.5.0.dist-info/entry_points.txt +3 -0
- tnfr-3.0.3.dist-info/licenses/LICENSE.txt → tnfr-8.5.0.dist-info/licenses/LICENSE.md +1 -1
- tnfr/constants.py +0 -183
- tnfr/dynamics.py +0 -543
- tnfr/helpers.py +0 -198
- tnfr/main.py +0 -37
- tnfr/operators.py +0 -296
- tnfr-3.0.3.dist-info/METADATA +0 -35
- tnfr-3.0.3.dist-info/RECORD +0 -13
- {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
- {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
tnfr/helpers.py
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
helpers.py — TNFR canónica
|
|
3
|
-
|
|
4
|
-
Utilidades transversales + cálculo de Índice de sentido (Si).
|
|
5
|
-
"""
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
from typing import Iterable, Dict, Any, Tuple, List
|
|
8
|
-
import math
|
|
9
|
-
from collections import deque
|
|
10
|
-
|
|
11
|
-
try:
|
|
12
|
-
import networkx as nx # solo para tipos
|
|
13
|
-
except Exception: # pragma: no cover
|
|
14
|
-
nx = None # type: ignore
|
|
15
|
-
|
|
16
|
-
from constants import DEFAULTS, ALIAS_VF, ALIAS_THETA, ALIAS_DNFR, ALIAS_EPI, ALIAS_SI
|
|
17
|
-
|
|
18
|
-
# -------------------------
|
|
19
|
-
# Utilidades numéricas
|
|
20
|
-
# -------------------------
|
|
21
|
-
|
|
22
|
-
def clamp(x: float, a: float, b: float) -> float:
|
|
23
|
-
return a if x < a else b if x > b else x
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def clamp_abs(x: float, m: float) -> float:
|
|
27
|
-
m = abs(m)
|
|
28
|
-
return clamp(x, -m, m)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def clamp01(x: float) -> float:
|
|
32
|
-
return clamp(x, 0.0, 1.0)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def list_mean(xs: Iterable[float], default: float = 0.0) -> float:
|
|
36
|
-
xs = list(xs)
|
|
37
|
-
return sum(xs) / len(xs) if xs else default
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def _wrap_angle(a: float) -> float:
|
|
41
|
-
"""Envuelve ángulo a (-π, π]."""
|
|
42
|
-
pi = math.pi
|
|
43
|
-
a = (a + pi) % (2 * pi) - pi
|
|
44
|
-
return a
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def phase_distance(a: float, b: float) -> float:
|
|
48
|
-
"""Distancia de fase normalizada en [0,1]. 0 = misma fase, 1 = opuesta."""
|
|
49
|
-
return abs(_wrap_angle(a - b)) / math.pi
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
# -------------------------
|
|
53
|
-
# Acceso a atributos con alias
|
|
54
|
-
# -------------------------
|
|
55
|
-
|
|
56
|
-
def _get_attr(d: Dict[str, Any], aliases: Iterable[str], default: float = 0.0) -> float:
|
|
57
|
-
for k in aliases:
|
|
58
|
-
if k in d:
|
|
59
|
-
try:
|
|
60
|
-
return float(d[k])
|
|
61
|
-
except Exception:
|
|
62
|
-
continue
|
|
63
|
-
return float(default)
|
|
64
|
-
|
|
65
|
-
def _set_attr(d, aliases, value: float) -> None:
|
|
66
|
-
for k in aliases:
|
|
67
|
-
if k in d:
|
|
68
|
-
d[k] = float(value)
|
|
69
|
-
return
|
|
70
|
-
d[next(iter(aliases))] = float(value)
|
|
71
|
-
|
|
72
|
-
# -------------------------
|
|
73
|
-
# Estadísticos vecinales
|
|
74
|
-
# -------------------------
|
|
75
|
-
|
|
76
|
-
def media_vecinal(G, n, aliases: Iterable[str], default: float = 0.0) -> float:
|
|
77
|
-
vals: List[float] = []
|
|
78
|
-
for v in G.neighbors(n):
|
|
79
|
-
vals.append(_get_attr(G.nodes[v], aliases, default))
|
|
80
|
-
return list_mean(vals, default)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def fase_media(G, n) -> float:
|
|
84
|
-
"""Promedio circular de las fases de los vecinos."""
|
|
85
|
-
import math
|
|
86
|
-
x = 0.0
|
|
87
|
-
y = 0.0
|
|
88
|
-
count = 0
|
|
89
|
-
for v in G.neighbors(n):
|
|
90
|
-
th = _get_attr(G.nodes[v], ALIAS_THETA, 0.0)
|
|
91
|
-
x += math.cos(th)
|
|
92
|
-
y += math.sin(th)
|
|
93
|
-
count += 1
|
|
94
|
-
if count == 0:
|
|
95
|
-
return _get_attr(G.nodes[n], ALIAS_THETA, 0.0)
|
|
96
|
-
return math.atan2(y / max(1, count), x / max(1, count))
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# -------------------------
|
|
100
|
-
# Historial de glifos por nodo
|
|
101
|
-
# -------------------------
|
|
102
|
-
|
|
103
|
-
def push_glifo(nd: Dict[str, Any], glifo: str, window: int) -> None:
|
|
104
|
-
hist = nd.setdefault("hist_glifos", deque(maxlen=window))
|
|
105
|
-
hist.append(str(glifo))
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def reciente_glifo(nd: Dict[str, Any], glifo: str, ventana: int) -> bool:
|
|
109
|
-
hist = nd.get("hist_glifos")
|
|
110
|
-
if not hist:
|
|
111
|
-
return False
|
|
112
|
-
last = list(hist)[-ventana:]
|
|
113
|
-
return str(glifo) in last
|
|
114
|
-
|
|
115
|
-
# -------------------------
|
|
116
|
-
# Callbacks Γ(R)
|
|
117
|
-
# -------------------------
|
|
118
|
-
|
|
119
|
-
def _ensure_callbacks(G):
|
|
120
|
-
"""Garantiza la estructura de callbacks en G.graph."""
|
|
121
|
-
cbs = G.graph.setdefault("callbacks", {
|
|
122
|
-
"before_step": [],
|
|
123
|
-
"after_step": [],
|
|
124
|
-
"on_remesh": [],
|
|
125
|
-
})
|
|
126
|
-
# normaliza claves por si vienen incompletas
|
|
127
|
-
for k in ("before_step", "after_step", "on_remesh"):
|
|
128
|
-
cbs.setdefault(k, [])
|
|
129
|
-
return cbs
|
|
130
|
-
|
|
131
|
-
def register_callback(G, event: str, func):
|
|
132
|
-
"""Registra un callback en G.graph['callbacks'][event]. Firma: func(G, ctx) -> None"""
|
|
133
|
-
if event not in ("before_step", "after_step", "on_remesh"):
|
|
134
|
-
raise ValueError(f"Evento desconocido: {event}")
|
|
135
|
-
cbs = _ensure_callbacks(G)
|
|
136
|
-
cbs[event].append(func)
|
|
137
|
-
return func
|
|
138
|
-
|
|
139
|
-
def invoke_callbacks(G, event: str, ctx: dict | None = None):
|
|
140
|
-
"""Invoca todos los callbacks registrados para `event` con el contexto `ctx`."""
|
|
141
|
-
cbs = _ensure_callbacks(G).get(event, [])
|
|
142
|
-
strict = bool(G.graph.get("CALLBACKS_STRICT", DEFAULTS["CALLBACKS_STRICT"]))
|
|
143
|
-
ctx = ctx or {}
|
|
144
|
-
for fn in list(cbs):
|
|
145
|
-
try:
|
|
146
|
-
fn(G, ctx)
|
|
147
|
-
except Exception as e:
|
|
148
|
-
if strict:
|
|
149
|
-
raise
|
|
150
|
-
G.graph.setdefault("_callback_errors", []).append({
|
|
151
|
-
"event": event, "step": ctx.get("step"), "error": repr(e), "fn": repr(fn)
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
# -------------------------
|
|
155
|
-
# Índice de sentido (Si)
|
|
156
|
-
# -------------------------
|
|
157
|
-
|
|
158
|
-
def compute_Si(G, *, inplace: bool = True) -> Dict[Any, float]:
|
|
159
|
-
"""Calcula Si por nodo y lo escribe en G.nodes[n]["Si"].
|
|
160
|
-
|
|
161
|
-
Si = α·νf_norm + β·(1 - disp_fase_local) + γ·(1 - |ΔNFR|/max|ΔNFR|)
|
|
162
|
-
"""
|
|
163
|
-
alpha = float(G.graph.get("SI_WEIGHTS", DEFAULTS["SI_WEIGHTS"]).get("alpha", 0.34))
|
|
164
|
-
beta = float(G.graph.get("SI_WEIGHTS", DEFAULTS["SI_WEIGHTS"]).get("beta", 0.33))
|
|
165
|
-
gamma = float(G.graph.get("SI_WEIGHTS", DEFAULTS["SI_WEIGHTS"]).get("gamma", 0.33))
|
|
166
|
-
s = alpha + beta + gamma
|
|
167
|
-
if s <= 0:
|
|
168
|
-
alpha = beta = gamma = 1/3
|
|
169
|
-
else:
|
|
170
|
-
alpha, beta, gamma = alpha/s, beta/s, gamma/s
|
|
171
|
-
|
|
172
|
-
# Normalización de νf en red
|
|
173
|
-
vfs = [abs(_get_attr(G.nodes[n], ALIAS_VF, 0.0)) for n in G.nodes()]
|
|
174
|
-
vfmax = max(vfs) if vfs else 1.0
|
|
175
|
-
# Normalización de ΔNFR
|
|
176
|
-
dnfrs = [abs(_get_attr(G.nodes[n], ALIAS_DNFR, 0.0)) for n in G.nodes()]
|
|
177
|
-
dnfrmax = max(dnfrs) if dnfrs else 1.0
|
|
178
|
-
|
|
179
|
-
out: Dict[Any, float] = {}
|
|
180
|
-
for n in G.nodes():
|
|
181
|
-
nd = G.nodes[n]
|
|
182
|
-
vf = _get_attr(nd, ALIAS_VF, 0.0)
|
|
183
|
-
vf_norm = 0.0 if vfmax == 0 else clamp01(abs(vf)/vfmax)
|
|
184
|
-
|
|
185
|
-
# dispersión de fase local
|
|
186
|
-
th_i = _get_attr(nd, ALIAS_THETA, 0.0)
|
|
187
|
-
th_bar = fase_media(G, n)
|
|
188
|
-
disp_fase = phase_distance(th_i, th_bar) # [0,1]
|
|
189
|
-
|
|
190
|
-
dnfr = _get_attr(nd, ALIAS_DNFR, 0.0)
|
|
191
|
-
dnfr_norm = 0.0 if dnfrmax == 0 else clamp01(abs(dnfr)/dnfrmax)
|
|
192
|
-
|
|
193
|
-
Si = alpha*vf_norm + beta*(1.0 - disp_fase) + gamma*(1.0 - dnfr_norm)
|
|
194
|
-
Si = clamp01(Si)
|
|
195
|
-
out[n] = Si
|
|
196
|
-
if inplace:
|
|
197
|
-
_set_attr(nd, ALIAS_SI, Si)
|
|
198
|
-
return out
|
tnfr/main.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
import argparse, sys
|
|
3
|
-
import networkx as nx
|
|
4
|
-
from . import preparar_red, run, __version__
|
|
5
|
-
|
|
6
|
-
def main(argv: list[str] | None = None) -> None:
|
|
7
|
-
p = argparse.ArgumentParser(
|
|
8
|
-
prog="tnfr",
|
|
9
|
-
description="TNFR canónica — demo CLI (red Erdős–Rényi + dinámica glífica)",
|
|
10
|
-
)
|
|
11
|
-
p.add_argument("--version", action="store_true", help="muestra versión y sale")
|
|
12
|
-
p.add_argument("--n", type=int, default=30, help="nodos (Erdős–Rényi)")
|
|
13
|
-
p.add_argument("--p", type=float, default=0.15, help="probabilidad de arista (Erdős–Rényi)")
|
|
14
|
-
p.add_argument("--steps", type=int, default=100, help="pasos a simular")
|
|
15
|
-
p.add_argument("--observer", action="store_true", help="adjunta observador estándar")
|
|
16
|
-
args = p.parse_args(argv)
|
|
17
|
-
|
|
18
|
-
if args.version:
|
|
19
|
-
print(__version__)
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
G = nx.erdos_renyi_graph(args.n, args.p)
|
|
23
|
-
preparar_red(G, ATTACH_STD_OBSERVER=bool(args.observer))
|
|
24
|
-
run(G, args.steps)
|
|
25
|
-
|
|
26
|
-
h = G.graph.get("history", {})
|
|
27
|
-
C = h.get("C_steps", [])[-1] if h.get("C_steps") else None
|
|
28
|
-
stab = h.get("stable_frac", [])[-1] if h.get("stable_frac") else None
|
|
29
|
-
R = h.get("kuramoto_R", [])[-1] if h.get("kuramoto_R") else None
|
|
30
|
-
|
|
31
|
-
print("TNFR terminado:")
|
|
32
|
-
if C is not None: print(f" C(t) ~ {C:.3f}")
|
|
33
|
-
if stab is not None: print(f" estable ~ {stab:.3f}")
|
|
34
|
-
if R is not None: print(f" R (Kuramoto) ~ {R:.3f}")
|
|
35
|
-
|
|
36
|
-
if __name__ == "__main__":
|
|
37
|
-
main(sys.argv[1:])
|
tnfr/operators.py
DELETED
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
# operators.py — TNFR canónica (ASCII-safe)
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
from typing import Dict, Any, Optional
|
|
4
|
-
import math
|
|
5
|
-
import random
|
|
6
|
-
import hashlib
|
|
7
|
-
|
|
8
|
-
from constants import DEFAULTS, ALIAS_VF, ALIAS_THETA, ALIAS_DNFR, ALIAS_EPI, ALIAS_D2EPI
|
|
9
|
-
from helpers import _get_attr, _set_attr, clamp, clamp01, list_mean, fase_media, push_glifo, invoke_callbacks
|
|
10
|
-
|
|
11
|
-
"""
|
|
12
|
-
Este módulo implementa:
|
|
13
|
-
- Los 13 glifos como operadores locales suaves.
|
|
14
|
-
- Un dispatcher `aplicar_glifo` que mapea el nombre del glifo (con apóstrofo tipográfico) a su función.
|
|
15
|
-
- RE’MESH de red: `aplicar_remesh_red` y `aplicar_remesh_si_estabilizacion_global`.
|
|
16
|
-
|
|
17
|
-
Nota sobre α (alpha) de RE’MESH: se toma por prioridad de
|
|
18
|
-
1) G.graph["GLYPH_FACTORS"]["REMESH_alpha"]
|
|
19
|
-
2) G.graph["REMESH_ALPHA"]
|
|
20
|
-
3) DEFAULTS["REMESH_ALPHA"]
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
# -------------------------
|
|
24
|
-
# Glifos (operadores locales)
|
|
25
|
-
# -------------------------
|
|
26
|
-
|
|
27
|
-
def op_AL(G, n): # A’L — Emisión
|
|
28
|
-
f = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("AL_boost", 0.05))
|
|
29
|
-
nd = G.nodes[n]
|
|
30
|
-
epi = _get_attr(nd, ALIAS_EPI, 0.0)
|
|
31
|
-
_set_attr(nd, ALIAS_EPI, epi + f)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def op_EN(G, n): # E’N — Recepción
|
|
35
|
-
mix = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("EN_mix", 0.25))
|
|
36
|
-
nd = G.nodes[n]
|
|
37
|
-
epi = _get_attr(nd, ALIAS_EPI, 0.0)
|
|
38
|
-
if G.degree(n) == 0:
|
|
39
|
-
return # sin vecinos no hay mezcla
|
|
40
|
-
epi_bar = list_mean(_get_attr(G.nodes[v], ALIAS_EPI, epi) for v in G.neighbors(n))
|
|
41
|
-
_set_attr(nd, ALIAS_EPI, (1 - mix) * epi + mix * epi_bar)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def op_IL(G, n): # I’L — Coherencia (reduce ΔNFR)
|
|
45
|
-
factor = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("IL_dnfr_factor", 0.7))
|
|
46
|
-
nd = G.nodes[n]
|
|
47
|
-
dnfr = _get_attr(nd, ALIAS_DNFR, 0.0)
|
|
48
|
-
_set_attr(nd, ALIAS_DNFR, factor * dnfr)
|
|
49
|
-
|
|
50
|
-
def op_OZ(G, n): # O’Z — Disonancia (aumenta ΔNFR o añade ruido)
|
|
51
|
-
factor = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("OZ_dnfr_factor", 1.3))
|
|
52
|
-
nd = G.nodes[n]
|
|
53
|
-
dnfr = _get_attr(nd, ALIAS_DNFR, 0.0)
|
|
54
|
-
if bool(G.graph.get("OZ_NOISE_MODE", False)):
|
|
55
|
-
base_seed = int(G.graph.get("RANDOM_SEED", 0))
|
|
56
|
-
step_idx = len(G.graph.get("history", {}).get("C_steps", []))
|
|
57
|
-
rnd = random.Random(base_seed + step_idx*1000003 + hash(("OZ", n)) % 1009)
|
|
58
|
-
sigma = float(G.graph.get("OZ_SIGMA", 0.1))
|
|
59
|
-
noise = sigma * (2.0 * rnd.random() - 1.0)
|
|
60
|
-
_set_attr(nd, ALIAS_DNFR, dnfr + noise)
|
|
61
|
-
else:
|
|
62
|
-
_set_attr(nd, ALIAS_DNFR, factor * dnfr if abs(dnfr) > 1e-9 else 0.1)
|
|
63
|
-
|
|
64
|
-
def op_UM(G, n): # U’M — Acoplamiento (empuja fase a la media local)
|
|
65
|
-
k = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("UM_theta_push", 0.25))
|
|
66
|
-
nd = G.nodes[n]
|
|
67
|
-
th = _get_attr(nd, ALIAS_THETA, 0.0)
|
|
68
|
-
thL = fase_media(G, n)
|
|
69
|
-
d = ((thL - th + math.pi) % (2 * math.pi) - math.pi)
|
|
70
|
-
_set_attr(nd, ALIAS_THETA, th + k * d)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def op_RA(G, n): # R’A — Resonancia (difusión EPI)
|
|
74
|
-
diff = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("RA_epi_diff", 0.15))
|
|
75
|
-
nd = G.nodes[n]
|
|
76
|
-
epi = _get_attr(nd, ALIAS_EPI, 0.0)
|
|
77
|
-
if G.degree(n) == 0:
|
|
78
|
-
return
|
|
79
|
-
epi_bar = list_mean(_get_attr(G.nodes[v], ALIAS_EPI, epi) for v in G.neighbors(n))
|
|
80
|
-
_set_attr(nd, ALIAS_EPI, epi + diff * (epi_bar - epi))
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def op_SHA(G, n): # SH’A — Silencio (baja νf)
|
|
84
|
-
factor = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("SHA_vf_factor", 0.85))
|
|
85
|
-
nd = G.nodes[n]
|
|
86
|
-
vf = _get_attr(nd, ALIAS_VF, 0.0)
|
|
87
|
-
_set_attr(nd, ALIAS_VF, factor * vf)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def op_VAL(G, n): # VA’L — Expansión (escala EPI)
|
|
91
|
-
s = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("VAL_scale", 1.15))
|
|
92
|
-
nd = G.nodes[n]
|
|
93
|
-
epi = _get_attr(nd, ALIAS_EPI, 0.0)
|
|
94
|
-
_set_attr(nd, ALIAS_EPI, s * epi)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def op_NUL(G, n): # NU’L — Contracción (escala EPI)
|
|
98
|
-
s = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("NUL_scale", 0.85))
|
|
99
|
-
nd = G.nodes[n]
|
|
100
|
-
epi = _get_attr(nd, ALIAS_EPI, 0.0)
|
|
101
|
-
_set_attr(nd, ALIAS_EPI, s * epi)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def op_THOL(G, n): # T’HOL — Autoorganización (inyecta aceleración)
|
|
105
|
-
a = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("THOL_accel", 0.10))
|
|
106
|
-
nd = G.nodes[n]
|
|
107
|
-
d2 = _get_attr(nd, ALIAS_D2EPI, 0.0)
|
|
108
|
-
_set_attr(nd, ALIAS_DNFR, _get_attr(nd, ALIAS_DNFR, 0.0) + a * d2)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
def op_ZHIR(G, n): # Z’HIR — Mutación (desplaza fase)
|
|
112
|
-
shift = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("ZHIR_theta_shift", 1.57079632679))
|
|
113
|
-
nd = G.nodes[n]
|
|
114
|
-
th = _get_attr(nd, ALIAS_THETA, 0.0)
|
|
115
|
-
_set_attr(nd, ALIAS_THETA, th + shift)
|
|
116
|
-
|
|
117
|
-
def op_NAV(G, n): # NA’V — Transición (jitter suave de ΔNFR)
|
|
118
|
-
nd = G.nodes[n]
|
|
119
|
-
dnfr = _get_attr(nd, ALIAS_DNFR, 0.0)
|
|
120
|
-
j = float(G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"]).get("NAV_jitter", 0.05))
|
|
121
|
-
if bool(G.graph.get("NAV_RANDOM", True)):
|
|
122
|
-
# jitter uniforme en [-j, j] con semilla reproducible
|
|
123
|
-
base_seed = int(G.graph.get("RANDOM_SEED", 0))
|
|
124
|
-
# opcional: pequeño offset para evitar misma secuencia en todos los nodos/pasos
|
|
125
|
-
step_idx = len(G.graph.get("history", {}).get("C_steps", []))
|
|
126
|
-
rnd = random.Random(base_seed + step_idx*1000003 + hash(n) % 1009)
|
|
127
|
-
jitter = j * (2.0 * rnd.random() - 1.0)
|
|
128
|
-
else:
|
|
129
|
-
# comportamiento determinista (compatibilidad previa)
|
|
130
|
-
jitter = j * (1 if dnfr >= 0 else -1)
|
|
131
|
-
_set_attr(nd, ALIAS_DNFR, dnfr + jitter)
|
|
132
|
-
|
|
133
|
-
def op_REMESH(G, n): # RE’MESH — se realiza a escala de red (no-op local con aviso)
|
|
134
|
-
# Loguea solo 1 vez por paso para no spamear
|
|
135
|
-
step_idx = len(G.graph.get("history", {}).get("C_steps", []))
|
|
136
|
-
last_warn = G.graph.get("_remesh_warn_step", None)
|
|
137
|
-
if last_warn != step_idx:
|
|
138
|
-
msg = "RE’MESH es a escala de red. Usa aplicar_remesh_si_estabilizacion_global(G) o aplicar_remesh_red(G)."
|
|
139
|
-
G.graph.setdefault("history", {}).setdefault("events", []).append(("warn", {"step": step_idx, "node": n, "msg": msg}))
|
|
140
|
-
G.graph["_remesh_warn_step"] = step_idx
|
|
141
|
-
# no cambia estado local
|
|
142
|
-
return
|
|
143
|
-
|
|
144
|
-
# -------------------------
|
|
145
|
-
# Dispatcher
|
|
146
|
-
# -------------------------
|
|
147
|
-
|
|
148
|
-
_NAME_TO_OP = {
|
|
149
|
-
"A’L": op_AL, "E’N": op_EN, "I’L": op_IL, "O’Z": op_OZ, "U’M": op_UM,
|
|
150
|
-
"R’A": op_RA, "SH’A": op_SHA, "VA’L": op_VAL, "NU’L": op_NUL,
|
|
151
|
-
"T’HOL": op_THOL, "Z’HIR": op_ZHIR, "NA’V": op_NAV, "RE’MESH": op_REMESH,
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
def aplicar_glifo(G, n, glifo: str, *, window: Optional[int] = None) -> None:
|
|
156
|
-
glifo = str(glifo)
|
|
157
|
-
op = _NAME_TO_OP.get(glifo)
|
|
158
|
-
if not op:
|
|
159
|
-
return
|
|
160
|
-
if window is None:
|
|
161
|
-
window = int(G.graph.get("GLYPH_HYSTERESIS_WINDOW", DEFAULTS["GLYPH_HYSTERESIS_WINDOW"]))
|
|
162
|
-
push_glifo(G.nodes[n], glifo, window)
|
|
163
|
-
op(G, n)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
# -------------------------
|
|
167
|
-
# RE’MESH de red (usa _epi_hist capturado en dynamics.step)
|
|
168
|
-
# -------------------------
|
|
169
|
-
|
|
170
|
-
def _remesh_alpha_info(G):
|
|
171
|
-
"""Devuelve (alpha, source) con precedencia explícita:
|
|
172
|
-
1) GLYPH_FACTORS["REMESH_alpha"] 2) G.graph["REMESH_ALPHA"] 3) DEFAULTS["REMESH_ALPHA"]"""
|
|
173
|
-
gf = G.graph.get("GLYPH_FACTORS", DEFAULTS["GLYPH_FACTORS"])
|
|
174
|
-
if "REMESH_alpha" in gf:
|
|
175
|
-
return float(gf["REMESH_alpha"]), "GLYPH_FACTORS"
|
|
176
|
-
if "REMESH_ALPHA" in G.graph:
|
|
177
|
-
return float(G.graph["REMESH_ALPHA"]), "G.graph"
|
|
178
|
-
return float(DEFAULTS["REMESH_ALPHA"]), "DEFAULTS"
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
def aplicar_remesh_red(G) -> None:
|
|
182
|
-
"""
|
|
183
|
-
RE’MESH a escala de red usando _epi_hist capturado en dynamics.step.
|
|
184
|
-
Loguea meta con alpha/tau/step + topo_hash y checksums/medias de EPI antes/después.
|
|
185
|
-
Precedencia de alpha: GLYPH_FACTORS → G.graph → DEFAULTS.
|
|
186
|
-
"""
|
|
187
|
-
tau = int(G.graph.get("REMESH_TAU", DEFAULTS["REMESH_TAU"]))
|
|
188
|
-
alpha, alpha_src = _remesh_alpha_info(G)
|
|
189
|
-
hist = G.graph.get("_epi_hist", [])
|
|
190
|
-
if len(hist) < tau + 1:
|
|
191
|
-
return
|
|
192
|
-
|
|
193
|
-
past = hist[-(tau + 1)]
|
|
194
|
-
|
|
195
|
-
# --- Topología + snapshot EPI (ANTES) ---
|
|
196
|
-
try:
|
|
197
|
-
n_nodes = G.number_of_nodes()
|
|
198
|
-
n_edges = G.number_of_edges()
|
|
199
|
-
degs = sorted(d for _, d in G.degree())
|
|
200
|
-
topo_str = f"n={n_nodes};m={n_edges};deg=" + ",".join(map(str, degs))
|
|
201
|
-
topo_hash = hashlib.sha1(topo_str.encode()).hexdigest()[:12]
|
|
202
|
-
except Exception:
|
|
203
|
-
topo_hash = None
|
|
204
|
-
|
|
205
|
-
def _epi_items():
|
|
206
|
-
for node in G.nodes():
|
|
207
|
-
yield node, _get_attr(G.nodes[node], ALIAS_EPI, 0.0)
|
|
208
|
-
|
|
209
|
-
epi_mean_before = list_mean(v for _, v in _epi_items())
|
|
210
|
-
epi_checksum_before = hashlib.sha1(
|
|
211
|
-
str(sorted((str(k), round(v, 6)) for k, v in _epi_items())).encode()
|
|
212
|
-
).hexdigest()[:12]
|
|
213
|
-
|
|
214
|
-
# --- Mezcla (1-α)·now + α·old ---
|
|
215
|
-
for n in G.nodes():
|
|
216
|
-
nd = G.nodes[n]
|
|
217
|
-
epi_now = _get_attr(nd, ALIAS_EPI, 0.0)
|
|
218
|
-
epi_old = float(past.get(n, epi_now))
|
|
219
|
-
_set_attr(nd, ALIAS_EPI, (1 - alpha) * epi_now + alpha * epi_old)
|
|
220
|
-
|
|
221
|
-
# --- Snapshot EPI (DESPUÉS) ---
|
|
222
|
-
epi_mean_after = list_mean(_get_attr(G.nodes[n], ALIAS_EPI, 0.0) for n in G.nodes())
|
|
223
|
-
epi_checksum_after = hashlib.sha1(
|
|
224
|
-
str(sorted((str(n), round(_get_attr(G.nodes[n], ALIAS_EPI, 0.0), 6)) for n in G.nodes())).encode()
|
|
225
|
-
).hexdigest()[:12]
|
|
226
|
-
|
|
227
|
-
# --- Metadatos y logging de evento ---
|
|
228
|
-
step_idx = len(G.graph.get("history", {}).get("C_steps", []))
|
|
229
|
-
meta = {
|
|
230
|
-
"alpha": alpha,
|
|
231
|
-
"alpha_source": alpha_src,
|
|
232
|
-
"tau": tau,
|
|
233
|
-
"step": step_idx,
|
|
234
|
-
# firmas
|
|
235
|
-
"topo_hash": topo_hash,
|
|
236
|
-
"epi_mean_before": float(epi_mean_before),
|
|
237
|
-
"epi_mean_after": float(epi_mean_after),
|
|
238
|
-
"epi_checksum_before": epi_checksum_before,
|
|
239
|
-
"epi_checksum_after": epi_checksum_after,
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
# Snapshot opcional de métricas recientes
|
|
243
|
-
h = G.graph.get("history", {})
|
|
244
|
-
if h:
|
|
245
|
-
if h.get("stable_frac"): meta["stable_frac_last"] = h["stable_frac"][-1]
|
|
246
|
-
if h.get("phase_sync"): meta["phase_sync_last"] = h["phase_sync"][-1]
|
|
247
|
-
if h.get("glyph_load_disr"): meta["glyph_disr_last"] = h["glyph_load_disr"][-1]
|
|
248
|
-
|
|
249
|
-
G.graph["_REMESH_META"] = meta
|
|
250
|
-
if G.graph.get("REMESH_LOG_EVENTS", DEFAULTS["REMESH_LOG_EVENTS"]):
|
|
251
|
-
ev = G.graph.setdefault("history", {}).setdefault("remesh_events", [])
|
|
252
|
-
ev.append(dict(meta))
|
|
253
|
-
|
|
254
|
-
# Callbacks Γ(R)
|
|
255
|
-
invoke_callbacks(G, "on_remesh", dict(meta))
|
|
256
|
-
|
|
257
|
-
def aplicar_remesh_si_estabilizacion_global(G, pasos_estables_consecutivos: Optional[int] = None) -> None:
|
|
258
|
-
# Ventanas y umbrales
|
|
259
|
-
w_estab = int(G.graph.get("REMESH_STABILITY_WINDOW", DEFAULTS["REMESH_STABILITY_WINDOW"]))
|
|
260
|
-
frac_req = float(G.graph.get("FRACTION_STABLE_REMESH", DEFAULTS["FRACTION_STABLE_REMESH"]))
|
|
261
|
-
req_extra = bool(G.graph.get("REMESH_REQUIRE_STABILITY", DEFAULTS["REMESH_REQUIRE_STABILITY"]))
|
|
262
|
-
min_sync = float(G.graph.get("REMESH_MIN_PHASE_SYNC", DEFAULTS["REMESH_MIN_PHASE_SYNC"]))
|
|
263
|
-
max_disr = float(G.graph.get("REMESH_MAX_GLYPH_DISR", DEFAULTS["REMESH_MAX_GLYPH_DISR"]))
|
|
264
|
-
|
|
265
|
-
hist = G.graph.setdefault("history", {"stable_frac": []})
|
|
266
|
-
sf = hist.get("stable_frac", [])
|
|
267
|
-
if len(sf) < w_estab:
|
|
268
|
-
return
|
|
269
|
-
# 1) Estabilidad por fracción de nodos estables
|
|
270
|
-
win_sf = sf[-w_estab:]
|
|
271
|
-
cond_sf = all(v >= frac_req for v in win_sf)
|
|
272
|
-
if not cond_sf:
|
|
273
|
-
return
|
|
274
|
-
# 2) Gating adicional (si está activado)
|
|
275
|
-
if req_extra:
|
|
276
|
-
# sincronía de fase (mayor mejor)
|
|
277
|
-
ps_ok = True
|
|
278
|
-
if "phase_sync" in hist and len(hist["phase_sync"]) >= w_estab:
|
|
279
|
-
win_ps = hist["phase_sync"][-w_estab:]
|
|
280
|
-
ps_ok = (sum(win_ps)/len(win_ps)) >= min_sync
|
|
281
|
-
# carga glífica disruptiva (menor mejor)
|
|
282
|
-
disr_ok = True
|
|
283
|
-
if "glyph_load_disr" in hist and len(hist["glyph_load_disr"]) >= w_estab:
|
|
284
|
-
win_disr = hist["glyph_load_disr"][-w_estab:]
|
|
285
|
-
disr_ok = (sum(win_disr)/len(win_disr)) <= max_disr
|
|
286
|
-
if not (ps_ok and disr_ok):
|
|
287
|
-
return
|
|
288
|
-
# 3) Cooldown
|
|
289
|
-
last = G.graph.get("_last_remesh_step", -10**9)
|
|
290
|
-
step_idx = len(sf)
|
|
291
|
-
cooldown = int(G.graph.get("REMESH_COOLDOWN_VENTANA", DEFAULTS["REMESH_COOLDOWN_VENTANA"]))
|
|
292
|
-
if step_idx - last < cooldown:
|
|
293
|
-
return
|
|
294
|
-
# 4) Aplicar y registrar
|
|
295
|
-
aplicar_remesh_red(G)
|
|
296
|
-
G.graph["_last_remesh_step"] = step_idx
|
tnfr-3.0.3.dist-info/METADATA
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: tnfr
|
|
3
|
-
Version: 3.0.3
|
|
4
|
-
Summary: TNFR canónica: dinámica glífica modular sobre redes.
|
|
5
|
-
Author: Fer
|
|
6
|
-
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://pypi.org/project/tnfr/
|
|
8
|
-
Project-URL: Repository, https://github.com/fermga/Teoria-de-la-naturaleza-fractal-resonante-TNFR-
|
|
9
|
-
Keywords: TNFR,fractal resonante,resonancia,glifos,networkx,dinámica,coherencia,EPI,Kuramoto
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
-
Classifier: Operating System :: OS Independent
|
|
19
|
-
Classifier: Intended Audience :: Science/Research
|
|
20
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
-
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
22
|
-
Requires-Python: >=3.9
|
|
23
|
-
Description-Content-Type: text/markdown
|
|
24
|
-
License-File: LICENSE.txt
|
|
25
|
-
Requires-Dist: networkx>=2.6
|
|
26
|
-
Dynamic: license-file
|
|
27
|
-
|
|
28
|
-
# tnfr
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Paquete **tnfr** (canónica). Orquesta dinámica glífica sobre grafos `networkx`.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
pip install tnfr
|
tnfr-3.0.3.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
tnfr/__init__.py,sha256=TRSH_QpQJthBeGIUFVmxTBNyth5KqRrRfRBnTeGzA40,2012
|
|
2
|
-
tnfr/constants.py,sha256=_775sPHussR9vgkWRCLC6dzwgk_1_lLnSlWT8sBWR3U,7677
|
|
3
|
-
tnfr/dynamics.py,sha256=7B38c9SVKLVFBrKHeJ1nXbghoRHfDs8Nl9CqUmCcAyI,23260
|
|
4
|
-
tnfr/helpers.py,sha256=tZJsDXc8k9HIfg8BA9cVUEFKBoX1Rfnuhurl2Fvxsy0,6017
|
|
5
|
-
tnfr/main.py,sha256=TEngteuC9MD7Ec9bNGuCC9ym-2ohbh202-HGArCR4tk,1506
|
|
6
|
-
tnfr/observers.py,sha256=MoC-xLJuMP-UYj8cpIVlgSbXDsE1Uj70Zy51PSH3AJY,5192
|
|
7
|
-
tnfr/ontosim.py,sha256=U0IeNVF8rFNhnmWWux91xDc0djTDZQkqRRosP6Z7FmE,5485
|
|
8
|
-
tnfr/operators.py,sha256=M6ahJL8IuB2y4qiEalge5EufCz0eEbhw-O4xfh3NpwE,12146
|
|
9
|
-
tnfr-3.0.3.dist-info/licenses/LICENSE.txt,sha256=xTjBNhy3N8pomFljrCkD1d34SmAEWv8hyJMMOjNMH0M,1071
|
|
10
|
-
tnfr-3.0.3.dist-info/METADATA,sha256=aZbWmWTeChR9K_uZSOizMzwggsi5Kv2pQ6Apu58ut8I,1325
|
|
11
|
-
tnfr-3.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
-
tnfr-3.0.3.dist-info/top_level.txt,sha256=Q2HJnvc5Rt2VHwVvyBTnNPT4SfmJWnCj7XUxxEvQa7c,5
|
|
13
|
-
tnfr-3.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|