tnfr 4.5.2__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 +275 -51
- 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 +117 -31
- tnfr/alias.pyi +108 -0
- tnfr/cache.py +6 -572
- tnfr/cache.pyi +16 -0
- tnfr/callback_utils.py +16 -38
- tnfr/callback_utils.pyi +79 -0
- tnfr/cli/__init__.py +34 -14
- tnfr/cli/__init__.pyi +26 -0
- tnfr/cli/arguments.py +211 -28
- tnfr/cli/arguments.pyi +27 -0
- tnfr/cli/execution.py +470 -50
- tnfr/cli/execution.pyi +70 -0
- tnfr/cli/utils.py +18 -3
- tnfr/cli/utils.pyi +8 -0
- tnfr/config/__init__.py +13 -0
- tnfr/config/__init__.pyi +10 -0
- tnfr/{constants_glyphs.py → config/constants.py} +26 -20
- tnfr/config/constants.pyi +12 -0
- tnfr/config/feature_flags.py +83 -0
- tnfr/{config.py → config/init.py} +11 -7
- tnfr/config/init.pyi +8 -0
- tnfr/config/operator_names.py +93 -0
- tnfr/config/operator_names.pyi +28 -0
- tnfr/config/presets.py +84 -0
- tnfr/config/presets.pyi +7 -0
- tnfr/constants/__init__.py +80 -29
- tnfr/constants/__init__.pyi +92 -0
- tnfr/constants/aliases.py +31 -0
- tnfr/constants/core.py +4 -4
- tnfr/constants/core.pyi +17 -0
- tnfr/constants/init.py +1 -1
- tnfr/constants/init.pyi +12 -0
- tnfr/constants/metric.py +7 -15
- tnfr/constants/metric.pyi +19 -0
- tnfr/dynamics/__init__.py +165 -633
- tnfr/dynamics/__init__.pyi +82 -0
- tnfr/dynamics/adaptation.py +267 -0
- tnfr/dynamics/aliases.py +23 -0
- tnfr/dynamics/coordination.py +385 -0
- tnfr/dynamics/dnfr.py +2283 -400
- tnfr/dynamics/dnfr.pyi +24 -0
- tnfr/dynamics/integrators.py +406 -98
- tnfr/dynamics/integrators.pyi +34 -0
- tnfr/dynamics/runtime.py +881 -0
- tnfr/dynamics/sampling.py +10 -5
- tnfr/dynamics/sampling.pyi +7 -0
- tnfr/dynamics/selectors.py +719 -0
- tnfr/execution.py +70 -48
- tnfr/execution.pyi +45 -0
- tnfr/flatten.py +13 -9
- tnfr/flatten.pyi +21 -0
- tnfr/gamma.py +66 -53
- tnfr/gamma.pyi +34 -0
- tnfr/glyph_history.py +110 -52
- tnfr/glyph_history.pyi +35 -0
- tnfr/glyph_runtime.py +16 -0
- tnfr/glyph_runtime.pyi +9 -0
- tnfr/immutable.py +69 -28
- tnfr/immutable.pyi +34 -0
- tnfr/initialization.py +16 -16
- tnfr/initialization.pyi +65 -0
- tnfr/io.py +6 -240
- tnfr/io.pyi +16 -0
- tnfr/locking.pyi +7 -0
- 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/__init__.pyi +20 -0
- tnfr/metrics/coherence.py +993 -324
- tnfr/metrics/common.py +23 -16
- tnfr/metrics/common.pyi +46 -0
- tnfr/metrics/core.py +251 -35
- tnfr/metrics/core.pyi +13 -0
- tnfr/metrics/diagnosis.py +708 -111
- tnfr/metrics/diagnosis.pyi +85 -0
- tnfr/metrics/export.py +27 -15
- tnfr/metrics/glyph_timing.py +232 -42
- tnfr/metrics/reporting.py +33 -22
- tnfr/metrics/reporting.pyi +12 -0
- tnfr/metrics/sense_index.py +987 -43
- tnfr/metrics/sense_index.pyi +9 -0
- tnfr/metrics/trig.py +214 -23
- tnfr/metrics/trig.pyi +13 -0
- tnfr/metrics/trig_cache.py +115 -22
- tnfr/metrics/trig_cache.pyi +10 -0
- tnfr/node.py +542 -136
- tnfr/node.pyi +178 -0
- tnfr/observers.py +152 -35
- tnfr/observers.pyi +31 -0
- tnfr/ontosim.py +23 -19
- tnfr/ontosim.pyi +28 -0
- tnfr/operators/__init__.py +601 -82
- tnfr/operators/__init__.pyi +45 -0
- tnfr/operators/definitions.py +513 -0
- tnfr/operators/definitions.pyi +78 -0
- tnfr/operators/grammar.py +760 -0
- tnfr/operators/jitter.py +107 -38
- tnfr/operators/jitter.pyi +11 -0
- tnfr/operators/registry.py +75 -0
- tnfr/operators/registry.pyi +13 -0
- tnfr/operators/remesh.py +149 -88
- tnfr/py.typed +0 -0
- tnfr/rng.py +46 -143
- tnfr/rng.pyi +14 -0
- tnfr/schemas/__init__.py +8 -0
- tnfr/schemas/grammar.json +94 -0
- tnfr/selector.py +25 -19
- tnfr/selector.pyi +19 -0
- tnfr/sense.py +72 -62
- tnfr/sense.pyi +23 -0
- tnfr/structural.py +522 -262
- tnfr/structural.pyi +69 -0
- tnfr/telemetry/__init__.py +35 -0
- tnfr/telemetry/cache_metrics.py +226 -0
- tnfr/telemetry/nu_f.py +423 -0
- tnfr/telemetry/nu_f.pyi +123 -0
- tnfr/telemetry/verbosity.py +37 -0
- tnfr/tokens.py +1 -3
- tnfr/tokens.pyi +36 -0
- tnfr/trace.py +270 -113
- tnfr/trace.pyi +40 -0
- tnfr/types.py +574 -6
- tnfr/types.pyi +331 -0
- tnfr/units.py +69 -0
- tnfr/units.pyi +16 -0
- tnfr/utils/__init__.py +217 -0
- tnfr/utils/__init__.pyi +202 -0
- tnfr/utils/cache.py +2395 -0
- tnfr/utils/cache.pyi +468 -0
- tnfr/utils/chunks.py +104 -0
- tnfr/utils/chunks.pyi +21 -0
- tnfr/{collections_utils.py → utils/data.py} +147 -90
- tnfr/utils/data.pyi +64 -0
- tnfr/utils/graph.py +85 -0
- tnfr/utils/graph.pyi +10 -0
- tnfr/utils/init.py +770 -0
- tnfr/utils/init.pyi +78 -0
- tnfr/utils/io.py +456 -0
- tnfr/{helpers → utils}/numeric.py +51 -24
- tnfr/utils/numeric.pyi +21 -0
- tnfr/validation/__init__.py +113 -0
- tnfr/validation/__init__.pyi +77 -0
- tnfr/validation/compatibility.py +95 -0
- tnfr/validation/compatibility.pyi +6 -0
- tnfr/validation/grammar.py +71 -0
- tnfr/validation/grammar.pyi +40 -0
- tnfr/validation/graph.py +138 -0
- tnfr/validation/graph.pyi +17 -0
- tnfr/validation/rules.py +281 -0
- tnfr/validation/rules.pyi +55 -0
- 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 +40 -0
- tnfr/validation/syntax.pyi +10 -0
- 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-7.0.0.dist-info/METADATA +179 -0
- tnfr-7.0.0.dist-info/RECORD +185 -0
- {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/licenses/LICENSE.md +1 -1
- tnfr/grammar.py +0 -344
- tnfr/graph_utils.py +0 -84
- tnfr/helpers/__init__.py +0 -71
- tnfr/import_utils.py +0 -228
- tnfr/json_utils.py +0 -162
- tnfr/logging_utils.py +0 -116
- tnfr/presets.py +0 -60
- tnfr/validators.py +0 -84
- tnfr/value_utils.py +0 -59
- tnfr-4.5.2.dist-info/METADATA +0 -379
- tnfr-4.5.2.dist-info/RECORD +0 -67
- {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/WHEEL +0 -0
- {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/entry_points.txt +0 -0
- {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/top_level.txt +0 -0
tnfr/cli/execution.pyi
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
import networkx as nx
|
|
8
|
+
|
|
9
|
+
from ..config import apply_config
|
|
10
|
+
from ..config.presets import get_preset
|
|
11
|
+
from ..constants import METRIC_DEFAULTS
|
|
12
|
+
from ..dynamics import (
|
|
13
|
+
default_glyph_selector,
|
|
14
|
+
parametric_glyph_selector,
|
|
15
|
+
run,
|
|
16
|
+
validate_canon,
|
|
17
|
+
)
|
|
18
|
+
from ..execution import CANONICAL_PRESET_NAME, play, seq
|
|
19
|
+
from ..flatten import parse_program_tokens
|
|
20
|
+
from ..glyph_history import ensure_history
|
|
21
|
+
from ..metrics import (
|
|
22
|
+
build_metrics_summary,
|
|
23
|
+
export_metrics,
|
|
24
|
+
glyph_top,
|
|
25
|
+
register_metrics_callbacks,
|
|
26
|
+
)
|
|
27
|
+
from ..metrics.core import _metrics_step
|
|
28
|
+
from ..ontosim import prepare_network
|
|
29
|
+
from ..sense import register_sigma_callback
|
|
30
|
+
from ..trace import register_trace
|
|
31
|
+
from ..types import Glyph, ProgramTokens
|
|
32
|
+
from ..utils import (
|
|
33
|
+
StructuredFileError,
|
|
34
|
+
get_logger,
|
|
35
|
+
json_dumps,
|
|
36
|
+
read_structured_file,
|
|
37
|
+
safe_write,
|
|
38
|
+
)
|
|
39
|
+
from .arguments import _args_to_dict
|
|
40
|
+
|
|
41
|
+
DEFAULT_SUMMARY_SERIES_LIMIT: int
|
|
42
|
+
logger: Any
|
|
43
|
+
|
|
44
|
+
def _save_json(path: str, data: Any) -> None: ...
|
|
45
|
+
def _attach_callbacks(G: nx.Graph) -> None: ...
|
|
46
|
+
def _persist_history(G: nx.Graph, args: argparse.Namespace) -> None: ...
|
|
47
|
+
def build_basic_graph(args: argparse.Namespace) -> nx.Graph: ...
|
|
48
|
+
def apply_cli_config(G: nx.Graph, args: argparse.Namespace) -> None: ...
|
|
49
|
+
def register_callbacks_and_observer(G: nx.Graph) -> None: ...
|
|
50
|
+
def _build_graph_from_args(args: argparse.Namespace) -> nx.Graph: ...
|
|
51
|
+
def _load_sequence(path: Path) -> ProgramTokens: ...
|
|
52
|
+
def resolve_program(
|
|
53
|
+
args: argparse.Namespace, default: Optional[ProgramTokens] = ...
|
|
54
|
+
) -> Optional[ProgramTokens]: ...
|
|
55
|
+
def run_program(
|
|
56
|
+
G: Optional[nx.Graph],
|
|
57
|
+
program: Optional[ProgramTokens],
|
|
58
|
+
args: argparse.Namespace,
|
|
59
|
+
) -> nx.Graph: ...
|
|
60
|
+
def _run_cli_program(
|
|
61
|
+
args: argparse.Namespace,
|
|
62
|
+
*,
|
|
63
|
+
default_program: Optional[ProgramTokens] = ...,
|
|
64
|
+
graph: Optional[nx.Graph] = ...,
|
|
65
|
+
) -> tuple[int, Optional[nx.Graph]]: ...
|
|
66
|
+
def _log_run_summaries(G: nx.Graph, args: argparse.Namespace) -> None: ...
|
|
67
|
+
def cmd_run(args: argparse.Namespace) -> int: ...
|
|
68
|
+
def cmd_sequence(args: argparse.Namespace) -> int: ...
|
|
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,10 +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
|
|
35
36
|
|
|
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
ADDED
tnfr/config/__init__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Configuration package for TNFR.
|
|
2
|
+
|
|
3
|
+
This package groups helpers and canonical defaults that orchestrate how
|
|
4
|
+
configuration payloads interact with the engine. The public API mirrors the
|
|
5
|
+
previous module level functions so downstream importers remain stable.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from .feature_flags import context_flags, get_flags
|
|
11
|
+
from .init import apply_config, load_config
|
|
12
|
+
|
|
13
|
+
__all__ = ("load_config", "apply_config", "get_flags", "context_flags")
|
tnfr/config/__init__.pyi
ADDED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Canonical glyph constants tied to configuration presets."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -6,10 +6,10 @@ import math
|
|
|
6
6
|
from types import MappingProxyType
|
|
7
7
|
from typing import Mapping
|
|
8
8
|
|
|
9
|
-
from
|
|
9
|
+
from ..types import Glyph
|
|
10
10
|
|
|
11
11
|
# -------------------------
|
|
12
|
-
#
|
|
12
|
+
# Canonical order and functional classifications
|
|
13
13
|
# -------------------------
|
|
14
14
|
|
|
15
15
|
GLYPHS_CANONICAL: tuple[str, ...] = (
|
|
@@ -30,26 +30,31 @@ GLYPHS_CANONICAL: tuple[str, ...] = (
|
|
|
30
30
|
|
|
31
31
|
GLYPHS_CANONICAL_SET: frozenset[str] = frozenset(GLYPHS_CANONICAL)
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
STABILIZERS: tuple[str, ...] = (
|
|
34
34
|
Glyph.IL.value,
|
|
35
35
|
Glyph.RA.value,
|
|
36
36
|
Glyph.UM.value,
|
|
37
37
|
Glyph.SHA.value,
|
|
38
38
|
)
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
DISRUPTORS: tuple[str, ...] = (
|
|
41
41
|
Glyph.OZ.value,
|
|
42
42
|
Glyph.ZHIR.value,
|
|
43
43
|
Glyph.NAV.value,
|
|
44
44
|
Glyph.THOL.value,
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
-
#
|
|
47
|
+
# General map of glyph groupings for cross-reference.
|
|
48
|
+
#
|
|
49
|
+
# Spanish keys (``estabilizadores`` / ``disruptivos``) were removed in TNFR 7.0
|
|
50
|
+
# to keep the public surface English-only. Code that still referenced those
|
|
51
|
+
# identifiers must switch to the canonical ``stabilizers`` / ``disruptors``
|
|
52
|
+
# entries or maintain a private compatibility layer.
|
|
48
53
|
GLYPH_GROUPS: Mapping[str, tuple[str, ...]] = MappingProxyType(
|
|
49
54
|
{
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
#
|
|
55
|
+
"stabilizers": STABILIZERS,
|
|
56
|
+
"disruptors": DISRUPTORS,
|
|
57
|
+
# Auxiliary groups for morphosyntactic metrics
|
|
53
58
|
"ID": (Glyph.OZ.value,),
|
|
54
59
|
"CM": (Glyph.ZHIR.value, Glyph.NAV.value),
|
|
55
60
|
"NE": (Glyph.IL.value, Glyph.THOL.value),
|
|
@@ -59,27 +64,28 @@ GLYPH_GROUPS: Mapping[str, tuple[str, ...]] = MappingProxyType(
|
|
|
59
64
|
)
|
|
60
65
|
|
|
61
66
|
# -------------------------
|
|
62
|
-
#
|
|
67
|
+
# Glyph angle map
|
|
63
68
|
# -------------------------
|
|
64
69
|
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
# "
|
|
70
|
+
# Canonical angles for all recognised glyphs. They are computed from the
|
|
71
|
+
# canonical order and orientation rules for the "stabilizers" and
|
|
72
|
+
# "disruptors" categories.
|
|
68
73
|
|
|
69
74
|
|
|
70
75
|
def _build_angle_map() -> dict[str, float]:
|
|
71
|
-
"""
|
|
76
|
+
"""Build the angle map in the σ-plane."""
|
|
77
|
+
|
|
72
78
|
step = 2 * math.pi / len(GLYPHS_CANONICAL)
|
|
73
79
|
canonical = {g: i * step for i, g in enumerate(GLYPHS_CANONICAL)}
|
|
74
80
|
angles = dict(canonical)
|
|
75
81
|
|
|
76
|
-
#
|
|
77
|
-
for idx, g in enumerate(
|
|
82
|
+
# Orientation rules
|
|
83
|
+
for idx, g in enumerate(STABILIZERS):
|
|
78
84
|
angles[g] = idx * math.pi / 4
|
|
79
|
-
for idx, g in enumerate(
|
|
85
|
+
for idx, g in enumerate(DISRUPTORS):
|
|
80
86
|
angles[g] = math.pi + idx * math.pi / 4
|
|
81
87
|
|
|
82
|
-
#
|
|
88
|
+
# Manual exceptions
|
|
83
89
|
angles[Glyph.VAL.value] = canonical[Glyph.RA.value]
|
|
84
90
|
angles[Glyph.NUL.value] = canonical[Glyph.ZHIR.value]
|
|
85
91
|
angles[Glyph.AL.value] = 0.0
|
|
@@ -91,8 +97,8 @@ ANGLE_MAP: Mapping[str, float] = MappingProxyType(_build_angle_map())
|
|
|
91
97
|
__all__ = (
|
|
92
98
|
"GLYPHS_CANONICAL",
|
|
93
99
|
"GLYPHS_CANONICAL_SET",
|
|
94
|
-
"
|
|
95
|
-
"
|
|
100
|
+
"STABILIZERS",
|
|
101
|
+
"DISRUPTORS",
|
|
96
102
|
"GLYPH_GROUPS",
|
|
97
103
|
"ANGLE_MAP",
|
|
98
104
|
)
|
|
@@ -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()
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Core configuration helpers."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
from collections.abc import Mapping
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
8
|
|
|
9
|
-
from
|
|
9
|
+
from ..constants import inject_defaults
|
|
10
|
+
from ..utils import read_structured_file
|
|
10
11
|
|
|
11
12
|
if TYPE_CHECKING: # pragma: no cover - only for type checkers
|
|
12
|
-
import networkx as nx
|
|
13
|
+
import networkx as nx
|
|
13
14
|
|
|
14
15
|
__all__ = ("load_config", "apply_config")
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
def load_config(path: str | Path) -> Mapping[str, Any]:
|
|
18
19
|
"""Read a JSON/YAML file and return a mapping with parameters."""
|
|
20
|
+
|
|
19
21
|
path_obj = path if isinstance(path, Path) else Path(path)
|
|
20
22
|
data = read_structured_file(path_obj)
|
|
21
23
|
if not isinstance(data, Mapping):
|
|
@@ -23,10 +25,12 @@ def load_config(path: str | Path) -> Mapping[str, Any]:
|
|
|
23
25
|
return data
|
|
24
26
|
|
|
25
27
|
|
|
26
|
-
def apply_config(G: nx.Graph, path: str | Path) -> None:
|
|
28
|
+
def apply_config(G: "nx.Graph", path: str | Path) -> None:
|
|
27
29
|
"""Inject parameters from ``path`` into ``G.graph``.
|
|
28
30
|
|
|
29
|
-
Reuses :func:`inject_defaults` to keep canonical default
|
|
31
|
+
Reuses :func:`tnfr.constants.inject_defaults` to keep canonical default
|
|
32
|
+
semantics.
|
|
30
33
|
"""
|
|
34
|
+
|
|
31
35
|
cfg = load_config(path)
|
|
32
36
|
inject_defaults(G, cfg, override=True)
|
tnfr/config/init.pyi
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Canonical operator name constants and reusable sets."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
# Canonical operator identifiers (English tokens)
|
|
8
|
+
EMISSION = "emission"
|
|
9
|
+
RECEPTION = "reception"
|
|
10
|
+
COHERENCE = "coherence"
|
|
11
|
+
DISSONANCE = "dissonance"
|
|
12
|
+
COUPLING = "coupling"
|
|
13
|
+
RESONANCE = "resonance"
|
|
14
|
+
SILENCE = "silence"
|
|
15
|
+
EXPANSION = "expansion"
|
|
16
|
+
CONTRACTION = "contraction"
|
|
17
|
+
SELF_ORGANIZATION = "self_organization"
|
|
18
|
+
MUTATION = "mutation"
|
|
19
|
+
TRANSITION = "transition"
|
|
20
|
+
RECURSIVITY = "recursivity"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Canonical collections -------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
CANONICAL_OPERATOR_NAMES = frozenset(
|
|
26
|
+
{
|
|
27
|
+
EMISSION,
|
|
28
|
+
RECEPTION,
|
|
29
|
+
COHERENCE,
|
|
30
|
+
DISSONANCE,
|
|
31
|
+
COUPLING,
|
|
32
|
+
RESONANCE,
|
|
33
|
+
SILENCE,
|
|
34
|
+
EXPANSION,
|
|
35
|
+
CONTRACTION,
|
|
36
|
+
SELF_ORGANIZATION,
|
|
37
|
+
MUTATION,
|
|
38
|
+
TRANSITION,
|
|
39
|
+
RECURSIVITY,
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
ALL_OPERATOR_NAMES = CANONICAL_OPERATOR_NAMES
|
|
44
|
+
ENGLISH_OPERATOR_NAMES = CANONICAL_OPERATOR_NAMES
|
|
45
|
+
|
|
46
|
+
VALID_START_OPERATORS = frozenset({EMISSION, RECURSIVITY})
|
|
47
|
+
INTERMEDIATE_OPERATORS = frozenset({DISSONANCE, COUPLING, RESONANCE})
|
|
48
|
+
VALID_END_OPERATORS = frozenset({SILENCE, TRANSITION, RECURSIVITY})
|
|
49
|
+
SELF_ORGANIZATION_CLOSURES = frozenset({SILENCE, CONTRACTION})
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def canonical_operator_name(name: str) -> str:
|
|
53
|
+
"""Return the canonical operator token for ``name``."""
|
|
54
|
+
|
|
55
|
+
return name
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def operator_display_name(name: str) -> str:
|
|
59
|
+
"""Return the display label for ``name`` (currently the canonical token)."""
|
|
60
|
+
|
|
61
|
+
return canonical_operator_name(name)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
__all__ = [
|
|
65
|
+
"EMISSION",
|
|
66
|
+
"RECEPTION",
|
|
67
|
+
"COHERENCE",
|
|
68
|
+
"DISSONANCE",
|
|
69
|
+
"COUPLING",
|
|
70
|
+
"RESONANCE",
|
|
71
|
+
"SILENCE",
|
|
72
|
+
"EXPANSION",
|
|
73
|
+
"CONTRACTION",
|
|
74
|
+
"SELF_ORGANIZATION",
|
|
75
|
+
"MUTATION",
|
|
76
|
+
"TRANSITION",
|
|
77
|
+
"RECURSIVITY",
|
|
78
|
+
"CANONICAL_OPERATOR_NAMES",
|
|
79
|
+
"ENGLISH_OPERATOR_NAMES",
|
|
80
|
+
"ALL_OPERATOR_NAMES",
|
|
81
|
+
"VALID_START_OPERATORS",
|
|
82
|
+
"INTERMEDIATE_OPERATORS",
|
|
83
|
+
"VALID_END_OPERATORS",
|
|
84
|
+
"SELF_ORGANIZATION_CLOSURES",
|
|
85
|
+
"canonical_operator_name",
|
|
86
|
+
"operator_display_name",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def __getattr__(name: str) -> Any:
|
|
91
|
+
"""Provide a consistent ``AttributeError`` when names are missing."""
|
|
92
|
+
|
|
93
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
__all__: Any
|
|
4
|
+
|
|
5
|
+
def __getattr__(name: str) -> Any: ...
|
|
6
|
+
|
|
7
|
+
ALL_OPERATOR_NAMES: Any
|
|
8
|
+
CANONICAL_OPERATOR_NAMES: Any
|
|
9
|
+
COHERENCE: Any
|
|
10
|
+
CONTRACTION: Any
|
|
11
|
+
COUPLING: Any
|
|
12
|
+
DISSONANCE: Any
|
|
13
|
+
EMISSION: Any
|
|
14
|
+
ENGLISH_OPERATOR_NAMES: Any
|
|
15
|
+
EXPANSION: Any
|
|
16
|
+
INTERMEDIATE_OPERATORS: Any
|
|
17
|
+
MUTATION: Any
|
|
18
|
+
RECEPTION: Any
|
|
19
|
+
RECURSIVITY: Any
|
|
20
|
+
RESONANCE: Any
|
|
21
|
+
SELF_ORGANIZATION: Any
|
|
22
|
+
SELF_ORGANIZATION_CLOSURES: Any
|
|
23
|
+
SILENCE: Any
|
|
24
|
+
TRANSITION: Any
|
|
25
|
+
VALID_END_OPERATORS: Any
|
|
26
|
+
VALID_START_OPERATORS: Any
|
|
27
|
+
canonical_operator_name: Any
|
|
28
|
+
operator_display_name: Any
|
tnfr/config/presets.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Predefined TNFR configuration sequences.
|
|
2
|
+
|
|
3
|
+
Only the canonical English preset identifiers are recognised.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from ..execution import (
|
|
9
|
+
CANONICAL_PRESET_NAME,
|
|
10
|
+
CANONICAL_PROGRAM_TOKENS,
|
|
11
|
+
block,
|
|
12
|
+
seq,
|
|
13
|
+
wait,
|
|
14
|
+
)
|
|
15
|
+
from ..types import Glyph, PresetTokens
|
|
16
|
+
|
|
17
|
+
__all__ = (
|
|
18
|
+
"get_preset",
|
|
19
|
+
"PREFERRED_PRESET_NAMES",
|
|
20
|
+
"legacy_preset_guidance",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
_PRIMARY_PRESETS: dict[str, PresetTokens] = {
|
|
25
|
+
"resonant_bootstrap": seq(
|
|
26
|
+
Glyph.AL,
|
|
27
|
+
Glyph.EN,
|
|
28
|
+
Glyph.IL,
|
|
29
|
+
Glyph.RA,
|
|
30
|
+
Glyph.VAL,
|
|
31
|
+
Glyph.UM,
|
|
32
|
+
wait(3),
|
|
33
|
+
Glyph.SHA,
|
|
34
|
+
),
|
|
35
|
+
"contained_mutation": seq(
|
|
36
|
+
Glyph.AL,
|
|
37
|
+
Glyph.EN,
|
|
38
|
+
block(Glyph.OZ, Glyph.ZHIR, Glyph.IL, repeat=2),
|
|
39
|
+
Glyph.RA,
|
|
40
|
+
Glyph.SHA,
|
|
41
|
+
),
|
|
42
|
+
"coupling_exploration": seq(
|
|
43
|
+
Glyph.AL,
|
|
44
|
+
Glyph.EN,
|
|
45
|
+
Glyph.IL,
|
|
46
|
+
Glyph.VAL,
|
|
47
|
+
Glyph.UM,
|
|
48
|
+
block(Glyph.OZ, Glyph.NAV, Glyph.IL, repeat=1),
|
|
49
|
+
Glyph.RA,
|
|
50
|
+
Glyph.SHA,
|
|
51
|
+
),
|
|
52
|
+
"fractal_expand": seq(
|
|
53
|
+
block(Glyph.THOL, Glyph.VAL, Glyph.UM, repeat=2, close=Glyph.NUL),
|
|
54
|
+
Glyph.RA,
|
|
55
|
+
),
|
|
56
|
+
"fractal_contract": seq(
|
|
57
|
+
block(Glyph.THOL, Glyph.NUL, Glyph.UM, repeat=2, close=Glyph.SHA),
|
|
58
|
+
Glyph.RA,
|
|
59
|
+
),
|
|
60
|
+
CANONICAL_PRESET_NAME: list(CANONICAL_PROGRAM_TOKENS),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
PREFERRED_PRESET_NAMES: tuple[str, ...] = tuple(_PRIMARY_PRESETS.keys())
|
|
64
|
+
|
|
65
|
+
_PRESETS: dict[str, PresetTokens] = {**_PRIMARY_PRESETS}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def legacy_preset_guidance(name: str) -> str | None:
|
|
69
|
+
"""Return CLI guidance for preset lookups.
|
|
70
|
+
|
|
71
|
+
Legacy aliases were removed; the function now always returns ``None``.
|
|
72
|
+
``name`` is accepted to preserve the public helper signature.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_preset(name: str) -> PresetTokens:
|
|
79
|
+
"""Return the preset token sequence identified by ``name``."""
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
return _PRESETS[name]
|
|
83
|
+
except KeyError:
|
|
84
|
+
raise KeyError(f"Preset not found: {name}") from None
|