tnfr 6.0.0__py3-none-any.whl → 7.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.
Potentially problematic release.
This version of tnfr might be problematic. Click here for more details.
- tnfr/__init__.py +50 -5
- tnfr/__init__.pyi +0 -7
- tnfr/_compat.py +0 -1
- tnfr/_generated_version.py +34 -0
- tnfr/_version.py +44 -2
- tnfr/alias.py +14 -13
- tnfr/alias.pyi +5 -37
- tnfr/cache.py +9 -729
- tnfr/cache.pyi +8 -224
- tnfr/callback_utils.py +16 -31
- tnfr/callback_utils.pyi +3 -29
- tnfr/cli/__init__.py +17 -11
- tnfr/cli/__init__.pyi +0 -21
- tnfr/cli/arguments.py +175 -14
- tnfr/cli/arguments.pyi +5 -11
- tnfr/cli/execution.py +434 -48
- tnfr/cli/execution.pyi +14 -24
- tnfr/cli/utils.py +20 -3
- tnfr/cli/utils.pyi +5 -5
- tnfr/config/__init__.py +2 -1
- tnfr/config/__init__.pyi +2 -0
- tnfr/config/feature_flags.py +83 -0
- tnfr/config/init.py +1 -1
- tnfr/config/operator_names.py +1 -14
- tnfr/config/presets.py +6 -26
- tnfr/constants/__init__.py +10 -13
- tnfr/constants/__init__.pyi +10 -22
- tnfr/constants/aliases.py +31 -0
- tnfr/constants/core.py +4 -3
- tnfr/constants/init.py +1 -1
- tnfr/constants/metric.py +3 -3
- tnfr/dynamics/__init__.py +64 -10
- tnfr/dynamics/__init__.pyi +3 -4
- tnfr/dynamics/adaptation.py +79 -13
- tnfr/dynamics/aliases.py +10 -9
- tnfr/dynamics/coordination.py +77 -35
- tnfr/dynamics/dnfr.py +575 -274
- tnfr/dynamics/dnfr.pyi +1 -10
- tnfr/dynamics/integrators.py +47 -33
- tnfr/dynamics/integrators.pyi +0 -1
- tnfr/dynamics/runtime.py +489 -129
- tnfr/dynamics/sampling.py +2 -0
- tnfr/dynamics/selectors.py +101 -62
- tnfr/execution.py +15 -8
- tnfr/execution.pyi +5 -25
- tnfr/flatten.py +7 -3
- tnfr/flatten.pyi +1 -8
- tnfr/gamma.py +22 -26
- tnfr/gamma.pyi +0 -6
- tnfr/glyph_history.py +37 -26
- tnfr/glyph_history.pyi +1 -19
- tnfr/glyph_runtime.py +16 -0
- tnfr/glyph_runtime.pyi +9 -0
- tnfr/immutable.py +20 -15
- tnfr/immutable.pyi +4 -7
- tnfr/initialization.py +5 -7
- tnfr/initialization.pyi +1 -9
- tnfr/io.py +6 -305
- tnfr/io.pyi +13 -8
- tnfr/mathematics/__init__.py +81 -0
- tnfr/mathematics/backend.py +426 -0
- tnfr/mathematics/dynamics.py +398 -0
- tnfr/mathematics/epi.py +254 -0
- tnfr/mathematics/generators.py +222 -0
- tnfr/mathematics/metrics.py +119 -0
- tnfr/mathematics/operators.py +233 -0
- tnfr/mathematics/operators_factory.py +71 -0
- tnfr/mathematics/projection.py +78 -0
- tnfr/mathematics/runtime.py +173 -0
- tnfr/mathematics/spaces.py +247 -0
- tnfr/mathematics/transforms.py +292 -0
- tnfr/metrics/__init__.py +10 -10
- tnfr/metrics/coherence.py +123 -94
- tnfr/metrics/common.py +22 -13
- tnfr/metrics/common.pyi +42 -11
- tnfr/metrics/core.py +72 -14
- tnfr/metrics/diagnosis.py +48 -57
- tnfr/metrics/diagnosis.pyi +3 -7
- tnfr/metrics/export.py +3 -5
- tnfr/metrics/glyph_timing.py +41 -31
- tnfr/metrics/reporting.py +13 -6
- tnfr/metrics/sense_index.py +884 -114
- tnfr/metrics/trig.py +167 -11
- tnfr/metrics/trig.pyi +1 -0
- tnfr/metrics/trig_cache.py +112 -15
- tnfr/node.py +400 -17
- tnfr/node.pyi +55 -38
- tnfr/observers.py +111 -8
- tnfr/observers.pyi +0 -15
- tnfr/ontosim.py +9 -6
- tnfr/ontosim.pyi +0 -5
- tnfr/operators/__init__.py +529 -42
- tnfr/operators/__init__.pyi +14 -0
- tnfr/operators/definitions.py +350 -18
- tnfr/operators/definitions.pyi +0 -14
- tnfr/operators/grammar.py +760 -0
- tnfr/operators/jitter.py +28 -22
- tnfr/operators/registry.py +7 -12
- tnfr/operators/registry.pyi +0 -2
- tnfr/operators/remesh.py +38 -61
- tnfr/rng.py +17 -300
- tnfr/schemas/__init__.py +8 -0
- tnfr/schemas/grammar.json +94 -0
- tnfr/selector.py +3 -4
- tnfr/selector.pyi +1 -1
- tnfr/sense.py +22 -24
- tnfr/sense.pyi +0 -7
- tnfr/structural.py +504 -21
- tnfr/structural.pyi +41 -18
- tnfr/telemetry/__init__.py +23 -1
- tnfr/telemetry/cache_metrics.py +226 -0
- tnfr/telemetry/nu_f.py +423 -0
- tnfr/telemetry/nu_f.pyi +123 -0
- tnfr/tokens.py +1 -4
- tnfr/tokens.pyi +1 -6
- tnfr/trace.py +20 -53
- tnfr/trace.pyi +9 -37
- tnfr/types.py +244 -15
- tnfr/types.pyi +200 -14
- tnfr/units.py +69 -0
- tnfr/units.pyi +16 -0
- tnfr/utils/__init__.py +107 -48
- tnfr/utils/__init__.pyi +80 -11
- tnfr/utils/cache.py +1705 -65
- tnfr/utils/cache.pyi +370 -58
- tnfr/utils/chunks.py +104 -0
- tnfr/utils/chunks.pyi +21 -0
- tnfr/utils/data.py +95 -5
- tnfr/utils/data.pyi +8 -17
- tnfr/utils/graph.py +2 -4
- tnfr/utils/init.py +31 -7
- tnfr/utils/init.pyi +4 -11
- tnfr/utils/io.py +313 -14
- tnfr/{helpers → utils}/numeric.py +50 -24
- tnfr/utils/numeric.pyi +21 -0
- tnfr/validation/__init__.py +92 -4
- tnfr/validation/__init__.pyi +77 -17
- tnfr/validation/compatibility.py +79 -43
- tnfr/validation/compatibility.pyi +4 -6
- tnfr/validation/grammar.py +55 -133
- tnfr/validation/grammar.pyi +37 -8
- tnfr/validation/graph.py +138 -0
- tnfr/validation/graph.pyi +17 -0
- tnfr/validation/rules.py +161 -74
- tnfr/validation/rules.pyi +55 -18
- tnfr/validation/runtime.py +263 -0
- tnfr/validation/runtime.pyi +31 -0
- tnfr/validation/soft_filters.py +170 -0
- tnfr/validation/soft_filters.pyi +37 -0
- tnfr/validation/spectral.py +159 -0
- tnfr/validation/spectral.pyi +46 -0
- tnfr/validation/syntax.py +28 -139
- tnfr/validation/syntax.pyi +7 -4
- tnfr/validation/window.py +39 -0
- tnfr/validation/window.pyi +1 -0
- tnfr/viz/__init__.py +9 -0
- tnfr/viz/matplotlib.py +246 -0
- {tnfr-6.0.0.dist-info → tnfr-7.0.0.dist-info}/METADATA +63 -19
- tnfr-7.0.0.dist-info/RECORD +185 -0
- {tnfr-6.0.0.dist-info → tnfr-7.0.0.dist-info}/licenses/LICENSE.md +1 -1
- tnfr/constants_glyphs.py +0 -16
- tnfr/constants_glyphs.pyi +0 -12
- tnfr/grammar.py +0 -25
- tnfr/grammar.pyi +0 -13
- tnfr/helpers/__init__.py +0 -151
- tnfr/helpers/__init__.pyi +0 -66
- tnfr/helpers/numeric.pyi +0 -12
- tnfr/presets.py +0 -15
- tnfr/presets.pyi +0 -7
- tnfr/utils/io.pyi +0 -10
- tnfr/utils/validators.py +0 -130
- tnfr/utils/validators.pyi +0 -19
- tnfr-6.0.0.dist-info/RECORD +0 -157
- {tnfr-6.0.0.dist-info → tnfr-7.0.0.dist-info}/WHEEL +0 -0
- {tnfr-6.0.0.dist-info → tnfr-7.0.0.dist-info}/entry_points.txt +0 -0
- {tnfr-6.0.0.dist-info → tnfr-7.0.0.dist-info}/top_level.txt +0 -0
tnfr/cli/execution.pyi
CHANGED
|
@@ -6,75 +6,65 @@ from typing import Any, Optional
|
|
|
6
6
|
|
|
7
7
|
import networkx as nx
|
|
8
8
|
|
|
9
|
+
from ..config import apply_config
|
|
10
|
+
from ..config.presets import get_preset
|
|
9
11
|
from ..constants import METRIC_DEFAULTS
|
|
10
12
|
from ..dynamics import (
|
|
11
|
-
run,
|
|
12
13
|
default_glyph_selector,
|
|
13
14
|
parametric_glyph_selector,
|
|
15
|
+
run,
|
|
14
16
|
validate_canon,
|
|
15
17
|
)
|
|
16
18
|
from ..execution import CANONICAL_PRESET_NAME, play, seq
|
|
17
19
|
from ..flatten import parse_program_tokens
|
|
18
20
|
from ..glyph_history import ensure_history
|
|
19
|
-
from ..io import read_structured_file, safe_write, StructuredFileError
|
|
20
21
|
from ..metrics import (
|
|
21
|
-
register_metrics_callbacks,
|
|
22
|
-
glyph_top,
|
|
23
|
-
export_metrics,
|
|
24
22
|
build_metrics_summary,
|
|
23
|
+
export_metrics,
|
|
24
|
+
glyph_top,
|
|
25
|
+
register_metrics_callbacks,
|
|
25
26
|
)
|
|
26
27
|
from ..metrics.core import _metrics_step
|
|
27
28
|
from ..ontosim import prepare_network
|
|
28
29
|
from ..sense import register_sigma_callback
|
|
29
30
|
from ..trace import register_trace
|
|
30
31
|
from ..types import Glyph, ProgramTokens
|
|
31
|
-
from ..utils import
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
from ..utils import (
|
|
33
|
+
StructuredFileError,
|
|
34
|
+
get_logger,
|
|
35
|
+
json_dumps,
|
|
36
|
+
read_structured_file,
|
|
37
|
+
safe_write,
|
|
38
|
+
)
|
|
35
39
|
from .arguments import _args_to_dict
|
|
36
40
|
|
|
37
41
|
DEFAULT_SUMMARY_SERIES_LIMIT: int
|
|
38
42
|
logger: Any
|
|
39
43
|
|
|
40
|
-
|
|
41
44
|
def _save_json(path: str, data: Any) -> None: ...
|
|
42
|
-
|
|
43
45
|
def _attach_callbacks(G: nx.Graph) -> None: ...
|
|
44
|
-
|
|
45
46
|
def _persist_history(G: nx.Graph, args: argparse.Namespace) -> None: ...
|
|
46
|
-
|
|
47
47
|
def build_basic_graph(args: argparse.Namespace) -> nx.Graph: ...
|
|
48
|
-
|
|
49
48
|
def apply_cli_config(G: nx.Graph, args: argparse.Namespace) -> None: ...
|
|
50
|
-
|
|
51
49
|
def register_callbacks_and_observer(G: nx.Graph) -> None: ...
|
|
52
|
-
|
|
53
50
|
def _build_graph_from_args(args: argparse.Namespace) -> nx.Graph: ...
|
|
54
|
-
|
|
55
51
|
def _load_sequence(path: Path) -> ProgramTokens: ...
|
|
56
|
-
|
|
57
52
|
def resolve_program(
|
|
58
53
|
args: argparse.Namespace, default: Optional[ProgramTokens] = ...
|
|
59
54
|
) -> Optional[ProgramTokens]: ...
|
|
60
|
-
|
|
61
55
|
def run_program(
|
|
62
56
|
G: Optional[nx.Graph],
|
|
63
57
|
program: Optional[ProgramTokens],
|
|
64
58
|
args: argparse.Namespace,
|
|
65
59
|
) -> nx.Graph: ...
|
|
66
|
-
|
|
67
60
|
def _run_cli_program(
|
|
68
61
|
args: argparse.Namespace,
|
|
69
62
|
*,
|
|
70
63
|
default_program: Optional[ProgramTokens] = ...,
|
|
71
64
|
graph: Optional[nx.Graph] = ...,
|
|
72
65
|
) -> tuple[int, Optional[nx.Graph]]: ...
|
|
73
|
-
|
|
74
66
|
def _log_run_summaries(G: nx.Graph, args: argparse.Namespace) -> None: ...
|
|
75
|
-
|
|
76
67
|
def cmd_run(args: argparse.Namespace) -> int: ...
|
|
77
|
-
|
|
78
68
|
def cmd_sequence(args: argparse.Namespace) -> int: ...
|
|
79
|
-
|
|
80
69
|
def cmd_metrics(args: argparse.Namespace) -> int: ...
|
|
70
|
+
def cmd_profile_si(args: argparse.Namespace) -> int: ...
|
tnfr/cli/utils.py
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from collections.abc import Iterable
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
8
|
+
from ..utils import normalize_optional_int
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
def spec(opt: str, /, **kwargs: Any) -> tuple[str, dict[str, Any]]:
|
|
9
12
|
"""Create an argument specification pair.
|
|
@@ -27,8 +30,22 @@ def spec(opt: str, /, **kwargs: Any) -> tuple[str, dict[str, Any]]:
|
|
|
27
30
|
"""
|
|
28
31
|
|
|
29
32
|
kwargs = dict(kwargs)
|
|
30
|
-
kwargs.setdefault(
|
|
31
|
-
"dest", opt.lstrip("-").replace("-", "_").replace(".", "_")
|
|
32
|
-
)
|
|
33
|
+
kwargs.setdefault("dest", opt.lstrip("-").replace("-", "_").replace(".", "_"))
|
|
33
34
|
kwargs.setdefault("default", None)
|
|
34
35
|
return opt, kwargs
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _parse_cli_variants(values: Iterable[Any] | None) -> list[int | None]:
|
|
39
|
+
"""Return a stable list of integer/``None`` variants for the CLI options."""
|
|
40
|
+
|
|
41
|
+
if values is None:
|
|
42
|
+
return [None]
|
|
43
|
+
parsed: list[int | None] = []
|
|
44
|
+
seen: set[int | None] = set()
|
|
45
|
+
for raw in values:
|
|
46
|
+
coerced = normalize_optional_int(raw, strict=True)
|
|
47
|
+
if coerced in seen:
|
|
48
|
+
continue
|
|
49
|
+
seen.add(coerced)
|
|
50
|
+
parsed.append(coerced)
|
|
51
|
+
return parsed or [None]
|
tnfr/cli/utils.pyi
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from typing import Any
|
|
4
5
|
|
|
5
|
-
def
|
|
6
|
+
def spec(opt: str, /, **kwargs: Any) -> tuple[str, dict[str, Any]]: ...
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
spec: Any
|
|
8
|
+
def _parse_cli_variants(values: Iterable[Any] | None) -> list[int | None]: ...
|
tnfr/config/__init__.py
CHANGED
|
@@ -7,6 +7,7 @@ previous module level functions so downstream importers remain stable.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
from .feature_flags import context_flags, get_flags
|
|
10
11
|
from .init import apply_config, load_config
|
|
11
12
|
|
|
12
|
-
__all__ = ("load_config", "apply_config")
|
|
13
|
+
__all__ = ("load_config", "apply_config", "get_flags", "context_flags")
|
tnfr/config/__init__.pyi
CHANGED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Math feature flag configuration helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from contextlib import contextmanager
|
|
7
|
+
from dataclasses import dataclass, replace
|
|
8
|
+
from typing import Iterator
|
|
9
|
+
|
|
10
|
+
__all__ = ("MathFeatureFlags", "get_flags", "context_flags")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class MathFeatureFlags:
|
|
15
|
+
"""Toggle optional mathematical behaviours in the engine."""
|
|
16
|
+
|
|
17
|
+
enable_math_validation: bool = False
|
|
18
|
+
enable_math_dynamics: bool = False
|
|
19
|
+
log_performance: bool = False
|
|
20
|
+
math_backend: str = "numpy"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
_TRUE_VALUES = {"1", "true", "on", "yes", "y", "t"}
|
|
24
|
+
_FALSE_VALUES = {"0", "false", "off", "no", "n", "f"}
|
|
25
|
+
|
|
26
|
+
_BASE_FLAGS: MathFeatureFlags | None = None
|
|
27
|
+
_FLAGS_STACK: list[MathFeatureFlags] = []
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _parse_env_flag(name: str, default: bool) -> bool:
|
|
31
|
+
value = os.getenv(name)
|
|
32
|
+
if value is None:
|
|
33
|
+
return default
|
|
34
|
+
lowered = value.strip().lower()
|
|
35
|
+
if lowered in _TRUE_VALUES:
|
|
36
|
+
return True
|
|
37
|
+
if lowered in _FALSE_VALUES:
|
|
38
|
+
return False
|
|
39
|
+
return default
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _load_base_flags() -> MathFeatureFlags:
|
|
43
|
+
global _BASE_FLAGS
|
|
44
|
+
if _BASE_FLAGS is None:
|
|
45
|
+
backend = os.getenv("TNFR_MATH_BACKEND")
|
|
46
|
+
backend_choice = backend.strip() if backend else "numpy"
|
|
47
|
+
_BASE_FLAGS = MathFeatureFlags(
|
|
48
|
+
enable_math_validation=_parse_env_flag(
|
|
49
|
+
"TNFR_ENABLE_MATH_VALIDATION", False
|
|
50
|
+
),
|
|
51
|
+
enable_math_dynamics=_parse_env_flag(
|
|
52
|
+
"TNFR_ENABLE_MATH_DYNAMICS", False
|
|
53
|
+
),
|
|
54
|
+
log_performance=_parse_env_flag("TNFR_LOG_PERF", False),
|
|
55
|
+
math_backend=backend_choice or "numpy",
|
|
56
|
+
)
|
|
57
|
+
return _BASE_FLAGS
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_flags() -> MathFeatureFlags:
|
|
61
|
+
"""Return the currently active feature flags."""
|
|
62
|
+
|
|
63
|
+
if _FLAGS_STACK:
|
|
64
|
+
return _FLAGS_STACK[-1]
|
|
65
|
+
return _load_base_flags()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@contextmanager
|
|
69
|
+
def context_flags(**overrides: bool) -> Iterator[MathFeatureFlags]:
|
|
70
|
+
"""Temporarily override math feature flags."""
|
|
71
|
+
|
|
72
|
+
invalid = set(overrides) - set(MathFeatureFlags.__annotations__)
|
|
73
|
+
if invalid:
|
|
74
|
+
invalid_names = ", ".join(sorted(invalid))
|
|
75
|
+
raise TypeError(f"Unknown flag overrides: {invalid_names}")
|
|
76
|
+
|
|
77
|
+
previous = get_flags()
|
|
78
|
+
next_flags = replace(previous, **overrides)
|
|
79
|
+
_FLAGS_STACK.append(next_flags)
|
|
80
|
+
try:
|
|
81
|
+
yield next_flags
|
|
82
|
+
finally:
|
|
83
|
+
_FLAGS_STACK.pop()
|
tnfr/config/init.py
CHANGED
|
@@ -7,7 +7,7 @@ from pathlib import Path
|
|
|
7
7
|
from typing import TYPE_CHECKING, Any
|
|
8
8
|
|
|
9
9
|
from ..constants import inject_defaults
|
|
10
|
-
from ..
|
|
10
|
+
from ..utils import read_structured_file
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING: # pragma: no cover - only for type checkers
|
|
13
13
|
import networkx as nx
|
tnfr/config/operator_names.py
CHANGED
|
@@ -4,7 +4,6 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
# Canonical operator identifiers (English tokens)
|
|
9
8
|
EMISSION = "emission"
|
|
10
9
|
RECEPTION = "reception"
|
|
@@ -50,13 +49,6 @@ VALID_END_OPERATORS = frozenset({SILENCE, TRANSITION, RECURSIVITY})
|
|
|
50
49
|
SELF_ORGANIZATION_CLOSURES = frozenset({SILENCE, CONTRACTION})
|
|
51
50
|
|
|
52
51
|
|
|
53
|
-
_LEGACY_COLLECTION_ALIASES: dict[str, str] = {
|
|
54
|
-
"INICIO_VALIDOS": "VALID_START_OPERATORS",
|
|
55
|
-
"TRAMO_INTERMEDIO": "INTERMEDIATE_OPERATORS",
|
|
56
|
-
"CIERRE_VALIDO": "VALID_END_OPERATORS",
|
|
57
|
-
"AUTOORGANIZACION_CIERRES": "SELF_ORGANIZATION_CLOSURES",
|
|
58
|
-
}
|
|
59
|
-
|
|
60
52
|
def canonical_operator_name(name: str) -> str:
|
|
61
53
|
"""Return the canonical operator token for ``name``."""
|
|
62
54
|
|
|
@@ -96,11 +88,6 @@ __all__ = [
|
|
|
96
88
|
|
|
97
89
|
|
|
98
90
|
def __getattr__(name: str) -> Any:
|
|
99
|
-
"""Provide
|
|
91
|
+
"""Provide a consistent ``AttributeError`` when names are missing."""
|
|
100
92
|
|
|
101
|
-
canonical = _LEGACY_COLLECTION_ALIASES.get(name)
|
|
102
|
-
if canonical is not None:
|
|
103
|
-
raise AttributeError(
|
|
104
|
-
f"module '{__name__}' has no attribute '{name}'; use '{canonical}' instead."
|
|
105
|
-
)
|
|
106
93
|
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
tnfr/config/presets.py
CHANGED
|
@@ -65,39 +65,19 @@ PREFERRED_PRESET_NAMES: tuple[str, ...] = tuple(_PRIMARY_PRESETS.keys())
|
|
|
65
65
|
_PRESETS: dict[str, PresetTokens] = {**_PRIMARY_PRESETS}
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
_LEGACY_PRESET_ALIASES: dict[str, str] = {
|
|
69
|
-
"arranque_resonante": "resonant_bootstrap",
|
|
70
|
-
"mutacion_contenida": "contained_mutation",
|
|
71
|
-
"exploracion_acople": "coupling_exploration",
|
|
72
|
-
"ejemplo_canonico": CANONICAL_PRESET_NAME,
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
68
|
def legacy_preset_guidance(name: str) -> str | None:
|
|
77
|
-
"""Return CLI guidance for
|
|
69
|
+
"""Return CLI guidance for preset lookups.
|
|
78
70
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
name:
|
|
82
|
-
Identifier received from the CLI.
|
|
83
|
-
|
|
84
|
-
Returns
|
|
85
|
-
-------
|
|
86
|
-
str | None
|
|
87
|
-
A human readable guidance string when ``name`` matches a removed
|
|
88
|
-
alias. ``None`` when no dedicated guidance is available.
|
|
71
|
+
Legacy aliases were removed; the function now always returns ``None``.
|
|
72
|
+
``name`` is accepted to preserve the public helper signature.
|
|
89
73
|
"""
|
|
90
74
|
|
|
91
|
-
|
|
92
|
-
if canonical is None:
|
|
93
|
-
return None
|
|
94
|
-
return (
|
|
95
|
-
f"Legacy preset identifier '{name}' was removed in TNFR 9.0. "
|
|
96
|
-
f"Use '{canonical}' instead."
|
|
97
|
-
)
|
|
75
|
+
return None
|
|
98
76
|
|
|
99
77
|
|
|
100
78
|
def get_preset(name: str) -> PresetTokens:
|
|
79
|
+
"""Return the preset token sequence identified by ``name``."""
|
|
80
|
+
|
|
101
81
|
try:
|
|
102
82
|
return _PRESETS[name]
|
|
103
83
|
except KeyError:
|
tnfr/constants/__init__.py
CHANGED
|
@@ -7,30 +7,28 @@ from collections.abc import Mapping
|
|
|
7
7
|
from types import MappingProxyType
|
|
8
8
|
from typing import Callable, TypeVar, cast
|
|
9
9
|
|
|
10
|
+
from ..immutable import _is_immutable
|
|
11
|
+
from ..types import GraphLike, TNFRConfigValue
|
|
10
12
|
from .core import CORE_DEFAULTS, REMESH_DEFAULTS
|
|
11
13
|
from .init import INIT_DEFAULTS
|
|
12
14
|
from .metric import (
|
|
15
|
+
COHERENCE,
|
|
16
|
+
DIAGNOSIS,
|
|
17
|
+
GRAMMAR_CANON,
|
|
13
18
|
METRIC_DEFAULTS,
|
|
19
|
+
METRICS,
|
|
14
20
|
SIGMA,
|
|
15
21
|
TRACE,
|
|
16
|
-
METRICS,
|
|
17
|
-
GRAMMAR_CANON,
|
|
18
|
-
COHERENCE,
|
|
19
|
-
DIAGNOSIS,
|
|
20
22
|
)
|
|
21
23
|
|
|
22
|
-
from ..immutable import _is_immutable
|
|
23
|
-
from ..types import GraphLike, TNFRConfigValue
|
|
24
|
-
|
|
25
24
|
T = TypeVar("T")
|
|
26
25
|
|
|
27
26
|
STATE_STABLE = "stable"
|
|
28
27
|
STATE_TRANSITION = "transition"
|
|
29
28
|
STATE_DISSONANT = "dissonant"
|
|
30
29
|
|
|
31
|
-
CANONICAL_STATE_TOKENS = frozenset(
|
|
32
|
-
|
|
33
|
-
)
|
|
30
|
+
CANONICAL_STATE_TOKENS = frozenset({STATE_STABLE, STATE_TRANSITION, STATE_DISSONANT})
|
|
31
|
+
|
|
34
32
|
|
|
35
33
|
def normalise_state_token(token: str) -> str:
|
|
36
34
|
"""Return the canonical English token for ``token``.
|
|
@@ -56,6 +54,7 @@ def normalise_state_token(token: str) -> str:
|
|
|
56
54
|
"state token must be one of 'stable', 'transition', or 'dissonant'"
|
|
57
55
|
)
|
|
58
56
|
|
|
57
|
+
|
|
59
58
|
try: # pragma: no cover - optional dependency
|
|
60
59
|
from ..utils import ensure_node_offset_map as _ensure_node_offset_map
|
|
61
60
|
except ImportError: # noqa: BLE001 - allow any import error
|
|
@@ -103,9 +102,7 @@ def inject_defaults(
|
|
|
103
102
|
for k, v in defaults.items():
|
|
104
103
|
if override or k not in G.graph:
|
|
105
104
|
G.graph[k] = (
|
|
106
|
-
v
|
|
107
|
-
if _is_immutable(v)
|
|
108
|
-
else cast(TNFRConfigValue, copy.deepcopy(v))
|
|
105
|
+
v if _is_immutable(v) else cast(TNFRConfigValue, copy.deepcopy(v))
|
|
109
106
|
)
|
|
110
107
|
G.graph["_tnfr_defaults_attached"] = True
|
|
111
108
|
if ensure_node_offset_map is not None:
|
tnfr/constants/__init__.pyi
CHANGED
|
@@ -3,18 +3,17 @@ from __future__ import annotations
|
|
|
3
3
|
from collections.abc import Mapping
|
|
4
4
|
from typing import Callable, TypeVar
|
|
5
5
|
|
|
6
|
-
from .core import CORE_DEFAULTS as CORE_DEFAULTS, REMESH_DEFAULTS as REMESH_DEFAULTS
|
|
7
|
-
from .init import INIT_DEFAULTS as INIT_DEFAULTS
|
|
8
|
-
from .metric import (
|
|
9
|
-
COHERENCE as COHERENCE,
|
|
10
|
-
DIAGNOSIS as DIAGNOSIS,
|
|
11
|
-
GRAMMAR_CANON as GRAMMAR_CANON,
|
|
12
|
-
METRICS as METRICS,
|
|
13
|
-
METRIC_DEFAULTS as METRIC_DEFAULTS,
|
|
14
|
-
SIGMA as SIGMA,
|
|
15
|
-
TRACE as TRACE,
|
|
16
|
-
)
|
|
17
6
|
from ..types import GraphLike, TNFRConfigValue
|
|
7
|
+
from .core import CORE_DEFAULTS as CORE_DEFAULTS
|
|
8
|
+
from .core import REMESH_DEFAULTS as REMESH_DEFAULTS
|
|
9
|
+
from .init import INIT_DEFAULTS as INIT_DEFAULTS
|
|
10
|
+
from .metric import COHERENCE as COHERENCE
|
|
11
|
+
from .metric import DIAGNOSIS as DIAGNOSIS
|
|
12
|
+
from .metric import GRAMMAR_CANON as GRAMMAR_CANON
|
|
13
|
+
from .metric import METRIC_DEFAULTS as METRIC_DEFAULTS
|
|
14
|
+
from .metric import METRICS as METRICS
|
|
15
|
+
from .metric import SIGMA as SIGMA
|
|
16
|
+
from .metric import TRACE as TRACE
|
|
18
17
|
|
|
19
18
|
T = TypeVar("T")
|
|
20
19
|
|
|
@@ -79,26 +78,15 @@ STATE_TRANSITION: str
|
|
|
79
78
|
STATE_DISSONANT: str
|
|
80
79
|
CANONICAL_STATE_TOKENS: frozenset[str]
|
|
81
80
|
|
|
82
|
-
|
|
83
81
|
def inject_defaults(
|
|
84
82
|
G: GraphLike,
|
|
85
83
|
defaults: Mapping[str, TNFRConfigValue] = ...,
|
|
86
84
|
override: bool = ...,
|
|
87
85
|
) -> None: ...
|
|
88
|
-
|
|
89
|
-
|
|
90
86
|
def merge_overrides(G: GraphLike, **overrides: TNFRConfigValue) -> None: ...
|
|
91
|
-
|
|
92
|
-
|
|
93
87
|
def get_param(G: GraphLike, key: str) -> TNFRConfigValue: ...
|
|
94
|
-
|
|
95
|
-
|
|
96
88
|
def get_graph_param(
|
|
97
89
|
G: GraphLike, key: str, cast: Callable[[object], T] = ...
|
|
98
90
|
) -> T | None: ...
|
|
99
|
-
|
|
100
|
-
|
|
101
91
|
def get_aliases(key: str) -> tuple[str, ...]: ...
|
|
102
|
-
|
|
103
|
-
|
|
104
92
|
def normalise_state_token(token: str) -> str: ...
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Shared alias constants for TNFR attributes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from . import get_aliases
|
|
6
|
+
|
|
7
|
+
ALIAS_VF = get_aliases("VF")
|
|
8
|
+
ALIAS_THETA = get_aliases("THETA")
|
|
9
|
+
ALIAS_DNFR = get_aliases("DNFR")
|
|
10
|
+
ALIAS_EPI = get_aliases("EPI")
|
|
11
|
+
ALIAS_EPI_KIND = get_aliases("EPI_KIND")
|
|
12
|
+
ALIAS_SI = get_aliases("SI")
|
|
13
|
+
ALIAS_DEPI = get_aliases("DEPI")
|
|
14
|
+
ALIAS_D2EPI = get_aliases("D2EPI")
|
|
15
|
+
ALIAS_DVF = get_aliases("DVF")
|
|
16
|
+
ALIAS_D2VF = get_aliases("D2VF")
|
|
17
|
+
ALIAS_DSI = get_aliases("DSI")
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"ALIAS_VF",
|
|
21
|
+
"ALIAS_THETA",
|
|
22
|
+
"ALIAS_DNFR",
|
|
23
|
+
"ALIAS_EPI",
|
|
24
|
+
"ALIAS_EPI_KIND",
|
|
25
|
+
"ALIAS_SI",
|
|
26
|
+
"ALIAS_DEPI",
|
|
27
|
+
"ALIAS_D2EPI",
|
|
28
|
+
"ALIAS_DVF",
|
|
29
|
+
"ALIAS_D2VF",
|
|
30
|
+
"ALIAS_DSI",
|
|
31
|
+
]
|
tnfr/constants/core.py
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from dataclasses import
|
|
6
|
-
from typing import Any, Mapping
|
|
5
|
+
from dataclasses import asdict, dataclass, field
|
|
7
6
|
from types import MappingProxyType
|
|
8
|
-
|
|
7
|
+
from typing import Any, Mapping
|
|
9
8
|
|
|
10
9
|
SELECTOR_THRESHOLD_DEFAULTS: Mapping[str, float] = MappingProxyType(
|
|
11
10
|
{
|
|
@@ -72,6 +71,7 @@ class CoreDefaults:
|
|
|
72
71
|
GLYPH_SELECTOR_MARGIN: float = 0.05
|
|
73
72
|
VF_ADAPT_TAU: int = 5
|
|
74
73
|
VF_ADAPT_MU: float = 0.1
|
|
74
|
+
HZ_STR_BRIDGE: float = 1.0
|
|
75
75
|
GLYPH_FACTORS: dict[str, float] = field(
|
|
76
76
|
default_factory=lambda: {
|
|
77
77
|
"AL_boost": 0.05,
|
|
@@ -151,6 +151,7 @@ class RemeshDefaults:
|
|
|
151
151
|
REMESH_ALPHA: float = 0.5
|
|
152
152
|
REMESH_ALPHA_HARD: bool = False
|
|
153
153
|
|
|
154
|
+
|
|
154
155
|
_core_defaults = asdict(CoreDefaults())
|
|
155
156
|
_remesh_defaults = asdict(RemeshDefaults())
|
|
156
157
|
|
tnfr/constants/init.py
CHANGED
tnfr/constants/metric.py
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from dataclasses import
|
|
6
|
-
from typing import Any
|
|
5
|
+
from dataclasses import asdict, dataclass, field
|
|
7
6
|
from types import MappingProxyType
|
|
7
|
+
from typing import Any
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@dataclass(frozen=True, slots=True)
|
|
@@ -27,7 +27,7 @@ class MetricDefaults:
|
|
|
27
27
|
default_factory=lambda: {
|
|
28
28
|
"enabled": True,
|
|
29
29
|
"weight": "Si", # "Si" | "EPI" | "1"
|
|
30
|
-
"smooth": 0.0, # EMA
|
|
30
|
+
"smooth": 0.0, # EMA over the global vector (0=off)
|
|
31
31
|
"history_key": "sigma_global",
|
|
32
32
|
"per_node": False,
|
|
33
33
|
}
|
tnfr/dynamics/__init__.py
CHANGED
|
@@ -1,9 +1,71 @@
|
|
|
1
|
-
"""Facade
|
|
1
|
+
"""Facade that keeps ΔNFR, νf and phase orchestration coherent across TNFR dynamics.
|
|
2
|
+
|
|
3
|
+
Attributes
|
|
4
|
+
----------
|
|
5
|
+
run : callable
|
|
6
|
+
Callable that fully manages the evolution loop, integrating the nodal
|
|
7
|
+
equation while enforcing ΔNFR hooks, νf adaptation and phase coordination
|
|
8
|
+
on every step.
|
|
9
|
+
step : callable
|
|
10
|
+
Callable entry point for a single iteration that reuses the
|
|
11
|
+
ΔNFR/νf/phase pipeline while letting callers interleave bespoke telemetry
|
|
12
|
+
or operator injections.
|
|
13
|
+
set_delta_nfr_hook : callable
|
|
14
|
+
Callable used to install custom ΔNFR supervision under
|
|
15
|
+
``G.graph['compute_delta_nfr']`` so each operator reorganization stays
|
|
16
|
+
coupled to νf drift and phase targets.
|
|
17
|
+
default_glyph_selector, parametric_glyph_selector : AbstractSelector
|
|
18
|
+
Selector implementations that choose glyphs according to ΔNFR trends,
|
|
19
|
+
νf ranges and phase synchrony, ensuring operator firing reinforces
|
|
20
|
+
coherence.
|
|
21
|
+
coordination, dnfr, integrators : module
|
|
22
|
+
Re-exported modules providing explicit control over phase alignment,
|
|
23
|
+
ΔNFR caches and integrator lifecycles to centralize orchestration.
|
|
24
|
+
ProcessPoolExecutor, apply_glyph, compute_Si : callable
|
|
25
|
+
Re-exported utilities for parallel selector evaluation, explicit glyph
|
|
26
|
+
execution and Si telemetry so ΔNFR, νf and phase traces remain observable.
|
|
27
|
+
|
|
28
|
+
Notes
|
|
29
|
+
-----
|
|
30
|
+
The facade aggregates runtime helpers that preserve canonical TNFR dynamics:
|
|
31
|
+
``dnfr`` manages ΔNFR preparation and caching, ``integrators`` drives the
|
|
32
|
+
numerical updates of νf and EPI, and ``coordination`` synchronizes global and
|
|
33
|
+
local phase. Complementary exports such as
|
|
34
|
+
:func:`~tnfr.dynamics.adaptation.adapt_vf_by_coherence` and
|
|
35
|
+
:func:`~tnfr.dynamics.coordination.coordinate_global_local_phase` allow custom
|
|
36
|
+
feedback loops without breaking operator closure.
|
|
37
|
+
|
|
38
|
+
Examples
|
|
39
|
+
--------
|
|
40
|
+
>>> from tnfr.constants import DNFR_PRIMARY, EPI_PRIMARY, VF_PRIMARY
|
|
41
|
+
>>> from tnfr.structural import Coherence, Emission, Resonance, create_nfr, run_sequence
|
|
42
|
+
>>> from tnfr.dynamics import parametric_glyph_selector, run, set_delta_nfr_hook, step
|
|
43
|
+
>>> G, node = create_nfr("seed", epi=0.22, vf=1.0)
|
|
44
|
+
>>> def regulate_delta(graph, *, n_jobs=None):
|
|
45
|
+
... for _, nd in graph.nodes(data=True):
|
|
46
|
+
... delta = nd[VF_PRIMARY] * 0.08
|
|
47
|
+
... nd[DNFR_PRIMARY] = delta
|
|
48
|
+
... nd[EPI_PRIMARY] += delta
|
|
49
|
+
... nd[VF_PRIMARY] += delta * 0.05
|
|
50
|
+
... return None
|
|
51
|
+
>>> set_delta_nfr_hook(G, regulate_delta, note="ΔNFR guided by νf")
|
|
52
|
+
>>> G.graph["glyph_selector"] = parametric_glyph_selector
|
|
53
|
+
>>> run_sequence(G, node, [Emission(), Resonance(), Coherence()])
|
|
54
|
+
>>> run(G, steps=2, dt=0.05)
|
|
55
|
+
>>> # Automatic integration keeps ΔNFR, νf and phase co-modulated.
|
|
56
|
+
>>> step(G, dt=0.05)
|
|
57
|
+
>>> # Manual control reuses the selector state to consolidate coherence traces.
|
|
58
|
+
"""
|
|
2
59
|
|
|
3
60
|
from __future__ import annotations
|
|
4
61
|
|
|
5
62
|
from concurrent.futures import ProcessPoolExecutor
|
|
6
63
|
|
|
64
|
+
from ..metrics.sense_index import compute_Si
|
|
65
|
+
from ..operators import apply_glyph, enforce_canonical_grammar, on_applied_glyph
|
|
66
|
+
from ..types import GlyphCode
|
|
67
|
+
from ..utils import get_numpy
|
|
68
|
+
from ..validation import apply_canonical_clamps, validate_canon
|
|
7
69
|
from . import coordination, dnfr, integrators
|
|
8
70
|
from .adaptation import adapt_vf_by_coherence
|
|
9
71
|
from .aliases import (
|
|
@@ -43,18 +105,14 @@ from .runtime import (
|
|
|
43
105
|
_run_validators,
|
|
44
106
|
_update_epi_hist,
|
|
45
107
|
_update_nodes,
|
|
46
|
-
apply_canonical_clamps,
|
|
47
108
|
run,
|
|
48
109
|
step,
|
|
49
|
-
validate_canon,
|
|
50
110
|
)
|
|
51
111
|
from .sampling import update_node_sample as _update_node_sample
|
|
52
112
|
from .selectors import (
|
|
53
113
|
AbstractSelector,
|
|
54
114
|
DefaultGlyphSelector,
|
|
55
|
-
GlyphCode,
|
|
56
115
|
ParametricGlyphSelector,
|
|
57
|
-
_SelectorPreselection,
|
|
58
116
|
_apply_glyphs,
|
|
59
117
|
_apply_selector,
|
|
60
118
|
_choose_glyph,
|
|
@@ -63,13 +121,10 @@ from .selectors import (
|
|
|
63
121
|
_prepare_selector_preselection,
|
|
64
122
|
_resolve_preselected_glyph,
|
|
65
123
|
_selector_parallel_jobs,
|
|
124
|
+
_SelectorPreselection,
|
|
66
125
|
default_glyph_selector,
|
|
67
126
|
parametric_glyph_selector,
|
|
68
127
|
)
|
|
69
|
-
from ..operators import apply_glyph
|
|
70
|
-
from ..metrics.sense_index import compute_Si
|
|
71
|
-
from ..utils import get_numpy
|
|
72
|
-
from ..validation.grammar import enforce_canonical_grammar, on_applied_glyph
|
|
73
128
|
|
|
74
129
|
__all__ = (
|
|
75
130
|
"coordination",
|
|
@@ -133,4 +188,3 @@ __all__ = (
|
|
|
133
188
|
"update_epi_via_nodal_equation",
|
|
134
189
|
"validate_canon",
|
|
135
190
|
)
|
|
136
|
-
|
tnfr/dynamics/__init__.pyi
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Any, Literal, Sequence
|
|
2
2
|
|
|
3
|
-
from tnfr.types import TNFRGraph
|
|
3
|
+
from tnfr.types import GlyphCode, TNFRGraph
|
|
4
|
+
from tnfr.validation import ValidationOutcome
|
|
4
5
|
|
|
5
6
|
__all__: tuple[str, ...]
|
|
6
7
|
|
|
@@ -16,7 +17,6 @@ ALIAS_VF: Sequence[str]
|
|
|
16
17
|
|
|
17
18
|
AbstractSelector: Any
|
|
18
19
|
DefaultGlyphSelector: Any
|
|
19
|
-
GlyphCode: Any
|
|
20
20
|
ParametricGlyphSelector: Any
|
|
21
21
|
_SelectorPreselection: Any
|
|
22
22
|
_apply_glyphs: Any
|
|
@@ -79,5 +79,4 @@ def update_epi_via_nodal_equation(
|
|
|
79
79
|
n_jobs: int | None = ...,
|
|
80
80
|
) -> None: ...
|
|
81
81
|
|
|
82
|
-
validate_canon:
|
|
83
|
-
|
|
82
|
+
def validate_canon(G: TNFRGraph) -> ValidationOutcome[TNFRGraph]: ...
|