tnfr 4.5.1__py3-none-any.whl → 6.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tnfr/__init__.py +270 -90
- tnfr/__init__.pyi +40 -0
- tnfr/_compat.py +11 -0
- tnfr/_version.py +7 -0
- tnfr/_version.pyi +7 -0
- tnfr/alias.py +631 -0
- tnfr/alias.pyi +140 -0
- tnfr/cache.py +732 -0
- tnfr/cache.pyi +232 -0
- tnfr/callback_utils.py +381 -0
- tnfr/callback_utils.pyi +105 -0
- tnfr/cli/__init__.py +89 -0
- tnfr/cli/__init__.pyi +47 -0
- tnfr/cli/arguments.py +199 -0
- tnfr/cli/arguments.pyi +33 -0
- tnfr/cli/execution.py +322 -0
- tnfr/cli/execution.pyi +80 -0
- tnfr/cli/utils.py +34 -0
- tnfr/cli/utils.pyi +8 -0
- tnfr/config/__init__.py +12 -0
- tnfr/config/__init__.pyi +8 -0
- tnfr/config/constants.py +104 -0
- tnfr/config/constants.pyi +12 -0
- tnfr/config/init.py +36 -0
- tnfr/config/init.pyi +8 -0
- tnfr/config/operator_names.py +106 -0
- tnfr/config/operator_names.pyi +28 -0
- tnfr/config/presets.py +104 -0
- tnfr/config/presets.pyi +7 -0
- tnfr/constants/__init__.py +228 -0
- tnfr/constants/__init__.pyi +104 -0
- tnfr/constants/core.py +158 -0
- tnfr/constants/core.pyi +17 -0
- tnfr/constants/init.py +31 -0
- tnfr/constants/init.pyi +12 -0
- tnfr/constants/metric.py +102 -0
- tnfr/constants/metric.pyi +19 -0
- tnfr/constants_glyphs.py +16 -0
- tnfr/constants_glyphs.pyi +12 -0
- tnfr/dynamics/__init__.py +136 -0
- tnfr/dynamics/__init__.pyi +83 -0
- tnfr/dynamics/adaptation.py +201 -0
- tnfr/dynamics/aliases.py +22 -0
- tnfr/dynamics/coordination.py +343 -0
- tnfr/dynamics/dnfr.py +2315 -0
- tnfr/dynamics/dnfr.pyi +33 -0
- tnfr/dynamics/integrators.py +561 -0
- tnfr/dynamics/integrators.pyi +35 -0
- tnfr/dynamics/runtime.py +521 -0
- tnfr/dynamics/sampling.py +34 -0
- tnfr/dynamics/sampling.pyi +7 -0
- tnfr/dynamics/selectors.py +680 -0
- tnfr/execution.py +216 -0
- tnfr/execution.pyi +65 -0
- tnfr/flatten.py +283 -0
- tnfr/flatten.pyi +28 -0
- tnfr/gamma.py +320 -89
- tnfr/gamma.pyi +40 -0
- tnfr/glyph_history.py +337 -0
- tnfr/glyph_history.pyi +53 -0
- tnfr/grammar.py +23 -153
- tnfr/grammar.pyi +13 -0
- tnfr/helpers/__init__.py +151 -0
- tnfr/helpers/__init__.pyi +66 -0
- tnfr/helpers/numeric.py +88 -0
- tnfr/helpers/numeric.pyi +12 -0
- tnfr/immutable.py +214 -0
- tnfr/immutable.pyi +37 -0
- tnfr/initialization.py +199 -0
- tnfr/initialization.pyi +73 -0
- tnfr/io.py +311 -0
- tnfr/io.pyi +11 -0
- tnfr/locking.py +37 -0
- tnfr/locking.pyi +7 -0
- tnfr/metrics/__init__.py +41 -0
- tnfr/metrics/__init__.pyi +20 -0
- tnfr/metrics/coherence.py +1469 -0
- tnfr/metrics/common.py +149 -0
- tnfr/metrics/common.pyi +15 -0
- tnfr/metrics/core.py +259 -0
- tnfr/metrics/core.pyi +13 -0
- tnfr/metrics/diagnosis.py +840 -0
- tnfr/metrics/diagnosis.pyi +89 -0
- tnfr/metrics/export.py +151 -0
- tnfr/metrics/glyph_timing.py +369 -0
- tnfr/metrics/reporting.py +152 -0
- tnfr/metrics/reporting.pyi +12 -0
- tnfr/metrics/sense_index.py +294 -0
- tnfr/metrics/sense_index.pyi +9 -0
- tnfr/metrics/trig.py +216 -0
- tnfr/metrics/trig.pyi +12 -0
- tnfr/metrics/trig_cache.py +105 -0
- tnfr/metrics/trig_cache.pyi +10 -0
- tnfr/node.py +255 -177
- tnfr/node.pyi +161 -0
- tnfr/observers.py +154 -150
- tnfr/observers.pyi +46 -0
- tnfr/ontosim.py +135 -134
- tnfr/ontosim.pyi +33 -0
- tnfr/operators/__init__.py +452 -0
- tnfr/operators/__init__.pyi +31 -0
- tnfr/operators/definitions.py +181 -0
- tnfr/operators/definitions.pyi +92 -0
- tnfr/operators/jitter.py +266 -0
- tnfr/operators/jitter.pyi +11 -0
- tnfr/operators/registry.py +80 -0
- tnfr/operators/registry.pyi +15 -0
- tnfr/operators/remesh.py +569 -0
- tnfr/presets.py +10 -23
- tnfr/presets.pyi +7 -0
- tnfr/py.typed +0 -0
- tnfr/rng.py +440 -0
- tnfr/rng.pyi +14 -0
- tnfr/selector.py +217 -0
- tnfr/selector.pyi +19 -0
- tnfr/sense.py +307 -142
- tnfr/sense.pyi +30 -0
- tnfr/structural.py +69 -164
- tnfr/structural.pyi +46 -0
- tnfr/telemetry/__init__.py +13 -0
- tnfr/telemetry/verbosity.py +37 -0
- tnfr/tokens.py +61 -0
- tnfr/tokens.pyi +41 -0
- tnfr/trace.py +520 -95
- tnfr/trace.pyi +68 -0
- tnfr/types.py +382 -17
- tnfr/types.pyi +145 -0
- tnfr/utils/__init__.py +158 -0
- tnfr/utils/__init__.pyi +133 -0
- tnfr/utils/cache.py +755 -0
- tnfr/utils/cache.pyi +156 -0
- tnfr/utils/data.py +267 -0
- tnfr/utils/data.pyi +73 -0
- tnfr/utils/graph.py +87 -0
- tnfr/utils/graph.pyi +10 -0
- tnfr/utils/init.py +746 -0
- tnfr/utils/init.pyi +85 -0
- tnfr/utils/io.py +157 -0
- tnfr/utils/io.pyi +10 -0
- tnfr/utils/validators.py +130 -0
- tnfr/utils/validators.pyi +19 -0
- tnfr/validation/__init__.py +25 -0
- tnfr/validation/__init__.pyi +17 -0
- tnfr/validation/compatibility.py +59 -0
- tnfr/validation/compatibility.pyi +8 -0
- tnfr/validation/grammar.py +149 -0
- tnfr/validation/grammar.pyi +11 -0
- tnfr/validation/rules.py +194 -0
- tnfr/validation/rules.pyi +18 -0
- tnfr/validation/syntax.py +151 -0
- tnfr/validation/syntax.pyi +7 -0
- tnfr-6.0.0.dist-info/METADATA +135 -0
- tnfr-6.0.0.dist-info/RECORD +157 -0
- tnfr/cli.py +0 -322
- tnfr/config.py +0 -41
- tnfr/constants.py +0 -277
- tnfr/dynamics.py +0 -814
- tnfr/helpers.py +0 -264
- tnfr/main.py +0 -47
- tnfr/metrics.py +0 -597
- tnfr/operators.py +0 -525
- tnfr/program.py +0 -176
- tnfr/scenarios.py +0 -34
- tnfr/validators.py +0 -38
- tnfr-4.5.1.dist-info/METADATA +0 -221
- tnfr-4.5.1.dist-info/RECORD +0 -28
- {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/WHEEL +0 -0
- {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/entry_points.txt +0 -0
- {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/licenses/LICENSE.md +0 -0
- {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"""Shared constants."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import copy
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from types import MappingProxyType
|
|
8
|
+
from typing import Callable, TypeVar, cast
|
|
9
|
+
|
|
10
|
+
from .core import CORE_DEFAULTS, REMESH_DEFAULTS
|
|
11
|
+
from .init import INIT_DEFAULTS
|
|
12
|
+
from .metric import (
|
|
13
|
+
METRIC_DEFAULTS,
|
|
14
|
+
SIGMA,
|
|
15
|
+
TRACE,
|
|
16
|
+
METRICS,
|
|
17
|
+
GRAMMAR_CANON,
|
|
18
|
+
COHERENCE,
|
|
19
|
+
DIAGNOSIS,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from ..immutable import _is_immutable
|
|
23
|
+
from ..types import GraphLike, TNFRConfigValue
|
|
24
|
+
|
|
25
|
+
T = TypeVar("T")
|
|
26
|
+
|
|
27
|
+
STATE_STABLE = "stable"
|
|
28
|
+
STATE_TRANSITION = "transition"
|
|
29
|
+
STATE_DISSONANT = "dissonant"
|
|
30
|
+
|
|
31
|
+
CANONICAL_STATE_TOKENS = frozenset(
|
|
32
|
+
{STATE_STABLE, STATE_TRANSITION, STATE_DISSONANT}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def normalise_state_token(token: str) -> str:
|
|
36
|
+
"""Return the canonical English token for ``token``.
|
|
37
|
+
|
|
38
|
+
The helper now enforces the English identifiers exclusively. Values that
|
|
39
|
+
do not match the canonical set raise :class:`ValueError` so callers can
|
|
40
|
+
surface explicit migration errors when legacy payloads are encountered.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
if not isinstance(token, str):
|
|
44
|
+
raise TypeError("state token must be a string")
|
|
45
|
+
|
|
46
|
+
stripped = token.strip()
|
|
47
|
+
lowered = stripped.lower()
|
|
48
|
+
|
|
49
|
+
if stripped in CANONICAL_STATE_TOKENS:
|
|
50
|
+
return stripped
|
|
51
|
+
|
|
52
|
+
if lowered in CANONICAL_STATE_TOKENS:
|
|
53
|
+
return lowered
|
|
54
|
+
|
|
55
|
+
raise ValueError(
|
|
56
|
+
"state token must be one of 'stable', 'transition', or 'dissonant'"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
try: # pragma: no cover - optional dependency
|
|
60
|
+
from ..utils import ensure_node_offset_map as _ensure_node_offset_map
|
|
61
|
+
except ImportError: # noqa: BLE001 - allow any import error
|
|
62
|
+
_ensure_node_offset_map = None
|
|
63
|
+
|
|
64
|
+
ensure_node_offset_map: Callable[[GraphLike], None] | None = _ensure_node_offset_map
|
|
65
|
+
|
|
66
|
+
# Exported sections
|
|
67
|
+
DEFAULT_SECTIONS: Mapping[str, Mapping[str, TNFRConfigValue]] = MappingProxyType(
|
|
68
|
+
{
|
|
69
|
+
"core": CORE_DEFAULTS,
|
|
70
|
+
"init": INIT_DEFAULTS,
|
|
71
|
+
"remesh": REMESH_DEFAULTS,
|
|
72
|
+
"metric": METRIC_DEFAULTS,
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Combined exported dictionary
|
|
77
|
+
# Merge the dictionaries from lowest to highest priority so that
|
|
78
|
+
# ``METRIC_DEFAULTS`` overrides the rest, mirroring the previous ``ChainMap``
|
|
79
|
+
# behaviour.
|
|
80
|
+
DEFAULTS: Mapping[str, TNFRConfigValue] = MappingProxyType(
|
|
81
|
+
CORE_DEFAULTS | INIT_DEFAULTS | REMESH_DEFAULTS | METRIC_DEFAULTS
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# -------------------------
|
|
85
|
+
# Utilities
|
|
86
|
+
# -------------------------
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def inject_defaults(
|
|
90
|
+
G: GraphLike,
|
|
91
|
+
defaults: Mapping[str, TNFRConfigValue] = DEFAULTS,
|
|
92
|
+
override: bool = False,
|
|
93
|
+
) -> None:
|
|
94
|
+
"""Inject ``defaults`` into ``G.graph``.
|
|
95
|
+
|
|
96
|
+
``defaults`` is usually ``DEFAULTS``, combining all sub-dictionaries.
|
|
97
|
+
If ``override`` is ``True`` existing values are overwritten. Immutable
|
|
98
|
+
values (numbers, strings, tuples, etc.) are assigned directly. Tuples are
|
|
99
|
+
inspected recursively; if any element is mutable, a ``deepcopy`` is made
|
|
100
|
+
to avoid shared state.
|
|
101
|
+
"""
|
|
102
|
+
G.graph.setdefault("_tnfr_defaults_attached", False)
|
|
103
|
+
for k, v in defaults.items():
|
|
104
|
+
if override or k not in G.graph:
|
|
105
|
+
G.graph[k] = (
|
|
106
|
+
v
|
|
107
|
+
if _is_immutable(v)
|
|
108
|
+
else cast(TNFRConfigValue, copy.deepcopy(v))
|
|
109
|
+
)
|
|
110
|
+
G.graph["_tnfr_defaults_attached"] = True
|
|
111
|
+
if ensure_node_offset_map is not None:
|
|
112
|
+
ensure_node_offset_map(G)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def merge_overrides(G: GraphLike, **overrides: TNFRConfigValue) -> None:
|
|
116
|
+
"""Apply specific changes to ``G.graph``.
|
|
117
|
+
|
|
118
|
+
Non-immutable values are deep-copied to avoid shared state with
|
|
119
|
+
:data:`DEFAULTS`.
|
|
120
|
+
"""
|
|
121
|
+
for key, value in overrides.items():
|
|
122
|
+
if key not in DEFAULTS:
|
|
123
|
+
raise KeyError(f"Unknown parameter: '{key}'")
|
|
124
|
+
G.graph[key] = (
|
|
125
|
+
value
|
|
126
|
+
if _is_immutable(value)
|
|
127
|
+
else cast(TNFRConfigValue, copy.deepcopy(value))
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def get_param(G: GraphLike, key: str) -> TNFRConfigValue:
|
|
132
|
+
"""Retrieve a parameter from ``G.graph`` or fall back to defaults."""
|
|
133
|
+
if key in G.graph:
|
|
134
|
+
return G.graph[key]
|
|
135
|
+
if key not in DEFAULTS:
|
|
136
|
+
raise KeyError(f"Unknown parameter: '{key}'")
|
|
137
|
+
return DEFAULTS[key]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def get_graph_param(
|
|
141
|
+
G: GraphLike, key: str, cast: Callable[[object], T] = float
|
|
142
|
+
) -> T | None:
|
|
143
|
+
"""Return ``key`` from ``G.graph`` applying ``cast``.
|
|
144
|
+
|
|
145
|
+
The ``cast`` argument must be a function (e.g. ``float``, ``int``,
|
|
146
|
+
``bool``). If the stored value is ``None`` it is returned without
|
|
147
|
+
casting.
|
|
148
|
+
"""
|
|
149
|
+
val = get_param(G, key)
|
|
150
|
+
return None if val is None else cast(val)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
# Canonical keys with ASCII spellings
|
|
154
|
+
VF_KEY = "νf"
|
|
155
|
+
THETA_KEY = "theta"
|
|
156
|
+
|
|
157
|
+
# Alias map for node attributes
|
|
158
|
+
ALIASES: dict[str, tuple[str, ...]] = {
|
|
159
|
+
"VF": (VF_KEY, "nu_f", "nu-f", "nu", "freq", "frequency"),
|
|
160
|
+
"THETA": (THETA_KEY, "phase"),
|
|
161
|
+
"DNFR": ("ΔNFR", "delta_nfr", "dnfr"),
|
|
162
|
+
"EPI": ("EPI", "psi", "PSI", "value"),
|
|
163
|
+
"EPI_KIND": ("EPI_kind", "epi_kind", "source_glyph"),
|
|
164
|
+
"SI": ("Si", "sense_index", "S_i", "sense", "meaning_index"),
|
|
165
|
+
"DEPI": ("dEPI_dt", "dpsi_dt", "dEPI", "velocity"),
|
|
166
|
+
"D2EPI": ("d2EPI_dt2", "d2psi_dt2", "d2EPI", "accel"),
|
|
167
|
+
"DVF": ("dνf_dt", "dvf_dt", "dnu_dt", "dvf"),
|
|
168
|
+
"D2VF": ("d2νf_dt2", "d2vf_dt2", "d2nu_dt2", "B"),
|
|
169
|
+
"DSI": ("δSi", "delta_Si", "dSi"),
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def get_aliases(key: str) -> tuple[str, ...]:
|
|
174
|
+
"""Return alias tuple for canonical ``key``."""
|
|
175
|
+
|
|
176
|
+
return ALIASES[key]
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
VF_PRIMARY = get_aliases("VF")[0]
|
|
180
|
+
THETA_PRIMARY = get_aliases("THETA")[0]
|
|
181
|
+
DNFR_PRIMARY = get_aliases("DNFR")[0]
|
|
182
|
+
EPI_PRIMARY = get_aliases("EPI")[0]
|
|
183
|
+
EPI_KIND_PRIMARY = get_aliases("EPI_KIND")[0]
|
|
184
|
+
SI_PRIMARY = get_aliases("SI")[0]
|
|
185
|
+
dEPI_PRIMARY = get_aliases("DEPI")[0]
|
|
186
|
+
D2EPI_PRIMARY = get_aliases("D2EPI")[0]
|
|
187
|
+
dVF_PRIMARY = get_aliases("DVF")[0]
|
|
188
|
+
D2VF_PRIMARY = get_aliases("D2VF")[0]
|
|
189
|
+
dSI_PRIMARY = get_aliases("DSI")[0]
|
|
190
|
+
|
|
191
|
+
__all__ = (
|
|
192
|
+
"CORE_DEFAULTS",
|
|
193
|
+
"INIT_DEFAULTS",
|
|
194
|
+
"REMESH_DEFAULTS",
|
|
195
|
+
"METRIC_DEFAULTS",
|
|
196
|
+
"SIGMA",
|
|
197
|
+
"TRACE",
|
|
198
|
+
"METRICS",
|
|
199
|
+
"GRAMMAR_CANON",
|
|
200
|
+
"COHERENCE",
|
|
201
|
+
"DIAGNOSIS",
|
|
202
|
+
"DEFAULTS",
|
|
203
|
+
"DEFAULT_SECTIONS",
|
|
204
|
+
"ALIASES",
|
|
205
|
+
"inject_defaults",
|
|
206
|
+
"merge_overrides",
|
|
207
|
+
"get_param",
|
|
208
|
+
"get_graph_param",
|
|
209
|
+
"get_aliases",
|
|
210
|
+
"VF_KEY",
|
|
211
|
+
"THETA_KEY",
|
|
212
|
+
"VF_PRIMARY",
|
|
213
|
+
"THETA_PRIMARY",
|
|
214
|
+
"DNFR_PRIMARY",
|
|
215
|
+
"EPI_PRIMARY",
|
|
216
|
+
"EPI_KIND_PRIMARY",
|
|
217
|
+
"SI_PRIMARY",
|
|
218
|
+
"dEPI_PRIMARY",
|
|
219
|
+
"D2EPI_PRIMARY",
|
|
220
|
+
"dVF_PRIMARY",
|
|
221
|
+
"D2VF_PRIMARY",
|
|
222
|
+
"dSI_PRIMARY",
|
|
223
|
+
"STATE_STABLE",
|
|
224
|
+
"STATE_TRANSITION",
|
|
225
|
+
"STATE_DISSONANT",
|
|
226
|
+
"CANONICAL_STATE_TOKENS",
|
|
227
|
+
"normalise_state_token",
|
|
228
|
+
)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import Callable, TypeVar
|
|
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
|
+
from ..types import GraphLike, TNFRConfigValue
|
|
18
|
+
|
|
19
|
+
T = TypeVar("T")
|
|
20
|
+
|
|
21
|
+
__all__ = (
|
|
22
|
+
"CORE_DEFAULTS",
|
|
23
|
+
"INIT_DEFAULTS",
|
|
24
|
+
"REMESH_DEFAULTS",
|
|
25
|
+
"METRIC_DEFAULTS",
|
|
26
|
+
"SIGMA",
|
|
27
|
+
"TRACE",
|
|
28
|
+
"METRICS",
|
|
29
|
+
"GRAMMAR_CANON",
|
|
30
|
+
"COHERENCE",
|
|
31
|
+
"DIAGNOSIS",
|
|
32
|
+
"DEFAULTS",
|
|
33
|
+
"DEFAULT_SECTIONS",
|
|
34
|
+
"ALIASES",
|
|
35
|
+
"inject_defaults",
|
|
36
|
+
"merge_overrides",
|
|
37
|
+
"get_param",
|
|
38
|
+
"get_graph_param",
|
|
39
|
+
"get_aliases",
|
|
40
|
+
"VF_KEY",
|
|
41
|
+
"THETA_KEY",
|
|
42
|
+
"VF_PRIMARY",
|
|
43
|
+
"THETA_PRIMARY",
|
|
44
|
+
"DNFR_PRIMARY",
|
|
45
|
+
"EPI_PRIMARY",
|
|
46
|
+
"EPI_KIND_PRIMARY",
|
|
47
|
+
"SI_PRIMARY",
|
|
48
|
+
"dEPI_PRIMARY",
|
|
49
|
+
"D2EPI_PRIMARY",
|
|
50
|
+
"dVF_PRIMARY",
|
|
51
|
+
"D2VF_PRIMARY",
|
|
52
|
+
"dSI_PRIMARY",
|
|
53
|
+
"STATE_STABLE",
|
|
54
|
+
"STATE_TRANSITION",
|
|
55
|
+
"STATE_DISSONANT",
|
|
56
|
+
"CANONICAL_STATE_TOKENS",
|
|
57
|
+
"normalise_state_token",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
ensure_node_offset_map: Callable[[GraphLike], None] | None
|
|
61
|
+
DEFAULT_SECTIONS: Mapping[str, Mapping[str, TNFRConfigValue]]
|
|
62
|
+
DEFAULTS: Mapping[str, TNFRConfigValue]
|
|
63
|
+
ALIASES: dict[str, tuple[str, ...]]
|
|
64
|
+
VF_KEY: str
|
|
65
|
+
THETA_KEY: str
|
|
66
|
+
VF_PRIMARY: str
|
|
67
|
+
THETA_PRIMARY: str
|
|
68
|
+
DNFR_PRIMARY: str
|
|
69
|
+
EPI_PRIMARY: str
|
|
70
|
+
EPI_KIND_PRIMARY: str
|
|
71
|
+
SI_PRIMARY: str
|
|
72
|
+
dEPI_PRIMARY: str
|
|
73
|
+
D2EPI_PRIMARY: str
|
|
74
|
+
dVF_PRIMARY: str
|
|
75
|
+
D2VF_PRIMARY: str
|
|
76
|
+
dSI_PRIMARY: str
|
|
77
|
+
STATE_STABLE: str
|
|
78
|
+
STATE_TRANSITION: str
|
|
79
|
+
STATE_DISSONANT: str
|
|
80
|
+
CANONICAL_STATE_TOKENS: frozenset[str]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def inject_defaults(
|
|
84
|
+
G: GraphLike,
|
|
85
|
+
defaults: Mapping[str, TNFRConfigValue] = ...,
|
|
86
|
+
override: bool = ...,
|
|
87
|
+
) -> None: ...
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def merge_overrides(G: GraphLike, **overrides: TNFRConfigValue) -> None: ...
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_param(G: GraphLike, key: str) -> TNFRConfigValue: ...
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get_graph_param(
|
|
97
|
+
G: GraphLike, key: str, cast: Callable[[object], T] = ...
|
|
98
|
+
) -> T | None: ...
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def get_aliases(key: str) -> tuple[str, ...]: ...
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def normalise_state_token(token: str) -> str: ...
|
tnfr/constants/core.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""Core constants."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, asdict, field
|
|
6
|
+
from typing import Any, Mapping
|
|
7
|
+
from types import MappingProxyType
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
SELECTOR_THRESHOLD_DEFAULTS: Mapping[str, float] = MappingProxyType(
|
|
11
|
+
{
|
|
12
|
+
"si_hi": 0.66,
|
|
13
|
+
"si_lo": 0.33,
|
|
14
|
+
"dnfr_hi": 0.50,
|
|
15
|
+
"dnfr_lo": 0.10,
|
|
16
|
+
"accel_hi": 0.50,
|
|
17
|
+
"accel_lo": 0.10,
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True, slots=True)
|
|
23
|
+
class CoreDefaults:
|
|
24
|
+
"""Default parameters for the core engine.
|
|
25
|
+
|
|
26
|
+
The fields are exported via :data:`CORE_DEFAULTS` and may therefore appear
|
|
27
|
+
unused to static analysis tools such as Vulture.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
DT: float = 1.0
|
|
31
|
+
INTEGRATOR_METHOD: str = "euler"
|
|
32
|
+
DT_MIN: float = 0.1
|
|
33
|
+
EPI_MIN: float = -1.0
|
|
34
|
+
EPI_MAX: float = 1.0
|
|
35
|
+
VF_MIN: float = 0.0
|
|
36
|
+
VF_MAX: float = 1.0
|
|
37
|
+
THETA_WRAP: bool = True
|
|
38
|
+
DNFR_WEIGHTS: dict[str, float] = field(
|
|
39
|
+
default_factory=lambda: {
|
|
40
|
+
"phase": 0.34,
|
|
41
|
+
"epi": 0.33,
|
|
42
|
+
"vf": 0.33,
|
|
43
|
+
"topo": 0.0,
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
SI_WEIGHTS: dict[str, float] = field(
|
|
47
|
+
default_factory=lambda: {"alpha": 0.34, "beta": 0.33, "gamma": 0.33}
|
|
48
|
+
)
|
|
49
|
+
PHASE_K_GLOBAL: float = 0.05
|
|
50
|
+
PHASE_K_LOCAL: float = 0.15
|
|
51
|
+
PHASE_ADAPT: dict[str, Any] = field(
|
|
52
|
+
default_factory=lambda: {
|
|
53
|
+
"enabled": True,
|
|
54
|
+
"R_hi": 0.90,
|
|
55
|
+
"R_lo": 0.60,
|
|
56
|
+
"disr_hi": 0.50,
|
|
57
|
+
"disr_lo": 0.25,
|
|
58
|
+
"kG_min": 0.01,
|
|
59
|
+
"kG_max": 0.20,
|
|
60
|
+
"kL_min": 0.05,
|
|
61
|
+
"kL_max": 0.25,
|
|
62
|
+
"up": 0.10,
|
|
63
|
+
"down": 0.07,
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
UM_COMPAT_THRESHOLD: float = 0.75
|
|
67
|
+
UM_CANDIDATE_MODE: str = "sample"
|
|
68
|
+
UM_CANDIDATE_COUNT: int = 0
|
|
69
|
+
GLYPH_HYSTERESIS_WINDOW: int = 7
|
|
70
|
+
AL_MAX_LAG: int = 5
|
|
71
|
+
EN_MAX_LAG: int = 3
|
|
72
|
+
GLYPH_SELECTOR_MARGIN: float = 0.05
|
|
73
|
+
VF_ADAPT_TAU: int = 5
|
|
74
|
+
VF_ADAPT_MU: float = 0.1
|
|
75
|
+
GLYPH_FACTORS: dict[str, float] = field(
|
|
76
|
+
default_factory=lambda: {
|
|
77
|
+
"AL_boost": 0.05,
|
|
78
|
+
"EN_mix": 0.25,
|
|
79
|
+
"IL_dnfr_factor": 0.7,
|
|
80
|
+
"OZ_dnfr_factor": 1.3,
|
|
81
|
+
"UM_theta_push": 0.25,
|
|
82
|
+
"RA_epi_diff": 0.15,
|
|
83
|
+
"SHA_vf_factor": 0.85,
|
|
84
|
+
"VAL_scale": 1.15,
|
|
85
|
+
"NUL_scale": 0.85,
|
|
86
|
+
"THOL_accel": 0.10,
|
|
87
|
+
"ZHIR_theta_shift": 1.57079632679,
|
|
88
|
+
"NAV_jitter": 0.05,
|
|
89
|
+
"NAV_eta": 0.5,
|
|
90
|
+
"REMESH_alpha": 0.5,
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
GLYPH_THRESHOLDS: dict[str, float] = field(
|
|
94
|
+
default_factory=lambda: {"hi": 0.66, "lo": 0.33, "dnfr": 1e-3}
|
|
95
|
+
)
|
|
96
|
+
NAV_RANDOM: bool = True
|
|
97
|
+
NAV_STRICT: bool = False
|
|
98
|
+
RANDOM_SEED: int = 0
|
|
99
|
+
JITTER_CACHE_SIZE: int = 256
|
|
100
|
+
OZ_NOISE_MODE: bool = False
|
|
101
|
+
OZ_SIGMA: float = 0.1
|
|
102
|
+
GRAMMAR: dict[str, Any] = field(
|
|
103
|
+
default_factory=lambda: {
|
|
104
|
+
"window": 3,
|
|
105
|
+
"avoid_repeats": ["ZHIR", "OZ", "THOL"],
|
|
106
|
+
"force_dnfr": 0.60,
|
|
107
|
+
"force_accel": 0.60,
|
|
108
|
+
"fallbacks": {"ZHIR": "NAV", "OZ": "ZHIR", "THOL": "NAV"},
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
SELECTOR_WEIGHTS: dict[str, float] = field(
|
|
112
|
+
default_factory=lambda: {"w_si": 0.5, "w_dnfr": 0.3, "w_accel": 0.2}
|
|
113
|
+
)
|
|
114
|
+
SELECTOR_THRESHOLDS: dict[str, float] = field(
|
|
115
|
+
default_factory=lambda: dict(SELECTOR_THRESHOLD_DEFAULTS)
|
|
116
|
+
)
|
|
117
|
+
GAMMA: dict[str, Any] = field(
|
|
118
|
+
default_factory=lambda: {"type": "none", "beta": 0.0, "R0": 0.0}
|
|
119
|
+
)
|
|
120
|
+
CALLBACKS_STRICT: bool = False
|
|
121
|
+
VALIDATORS_STRICT: bool = False
|
|
122
|
+
PROGRAM_TRACE_MAXLEN: int = 50
|
|
123
|
+
HISTORY_MAXLEN: int = 0
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@dataclass(frozen=True, slots=True)
|
|
127
|
+
class RemeshDefaults:
|
|
128
|
+
"""Default parameters for the remeshing subsystem.
|
|
129
|
+
|
|
130
|
+
As with :class:`CoreDefaults`, the fields are exported via
|
|
131
|
+
:data:`REMESH_DEFAULTS` and may look unused to static analysers.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
EPS_DNFR_STABLE: float = 1e-3
|
|
135
|
+
EPS_DEPI_STABLE: float = 1e-3
|
|
136
|
+
FRACTION_STABLE_REMESH: float = 0.80
|
|
137
|
+
REMESH_COOLDOWN_WINDOW: int = 20
|
|
138
|
+
REMESH_COOLDOWN_TS: float = 0.0
|
|
139
|
+
REMESH_REQUIRE_STABILITY: bool = True
|
|
140
|
+
REMESH_STABILITY_WINDOW: int = 25
|
|
141
|
+
REMESH_MIN_PHASE_SYNC: float = 0.85
|
|
142
|
+
REMESH_MAX_GLYPH_DISR: float = 0.35
|
|
143
|
+
REMESH_MIN_SIGMA_MAG: float = 0.50
|
|
144
|
+
REMESH_MIN_KURAMOTO_R: float = 0.80
|
|
145
|
+
REMESH_MIN_SI_HI_FRAC: float = 0.50
|
|
146
|
+
REMESH_LOG_EVENTS: bool = True
|
|
147
|
+
REMESH_MODE: str = "knn"
|
|
148
|
+
REMESH_COMMUNITY_K: int = 2
|
|
149
|
+
REMESH_TAU_GLOBAL: int = 8
|
|
150
|
+
REMESH_TAU_LOCAL: int = 4
|
|
151
|
+
REMESH_ALPHA: float = 0.5
|
|
152
|
+
REMESH_ALPHA_HARD: bool = False
|
|
153
|
+
|
|
154
|
+
_core_defaults = asdict(CoreDefaults())
|
|
155
|
+
_remesh_defaults = asdict(RemeshDefaults())
|
|
156
|
+
|
|
157
|
+
CORE_DEFAULTS = MappingProxyType(_core_defaults)
|
|
158
|
+
REMESH_DEFAULTS = MappingProxyType(_remesh_defaults)
|
tnfr/constants/core.pyi
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
__all__: Any
|
|
4
|
+
|
|
5
|
+
def __getattr__(name: str) -> Any: ...
|
|
6
|
+
|
|
7
|
+
CORE_DEFAULTS: Any
|
|
8
|
+
CoreDefaults: Any
|
|
9
|
+
Mapping: Any
|
|
10
|
+
MappingProxyType: Any
|
|
11
|
+
REMESH_DEFAULTS: Any
|
|
12
|
+
RemeshDefaults: Any
|
|
13
|
+
SELECTOR_THRESHOLD_DEFAULTS: Any
|
|
14
|
+
annotations: Any
|
|
15
|
+
asdict: Any
|
|
16
|
+
dataclass: Any
|
|
17
|
+
field: Any
|
tnfr/constants/init.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Initialization constants."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, asdict
|
|
6
|
+
import math
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True, slots=True)
|
|
10
|
+
class InitDefaults:
|
|
11
|
+
"""Default parameters for node initialisation.
|
|
12
|
+
|
|
13
|
+
The fields are collected into :data:`INIT_DEFAULTS` and may therefore
|
|
14
|
+
appear unused to tools like Vulture.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
INIT_RANDOM_PHASE: bool = True
|
|
18
|
+
INIT_THETA_MIN: float = -math.pi
|
|
19
|
+
INIT_THETA_MAX: float = math.pi
|
|
20
|
+
INIT_VF_MODE: str = "uniform"
|
|
21
|
+
INIT_VF_MIN: float | None = None
|
|
22
|
+
INIT_VF_MAX: float | None = None
|
|
23
|
+
INIT_VF_MEAN: float = 0.5
|
|
24
|
+
INIT_VF_STD: float = 0.15
|
|
25
|
+
INIT_VF_CLAMP_TO_LIMITS: bool = True
|
|
26
|
+
INIT_SI_MIN: float = 0.4
|
|
27
|
+
INIT_SI_MAX: float = 0.7
|
|
28
|
+
INIT_EPI_VALUE: float = 0.0
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
INIT_DEFAULTS = asdict(InitDefaults())
|
tnfr/constants/init.pyi
ADDED
tnfr/constants/metric.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""Metric constants."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, asdict, field
|
|
6
|
+
from typing import Any
|
|
7
|
+
from types import MappingProxyType
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True, slots=True)
|
|
11
|
+
class MetricDefaults:
|
|
12
|
+
"""Default parameters for metric computation.
|
|
13
|
+
|
|
14
|
+
The fields are gathered into :data:`METRIC_DEFAULTS` and exposed through
|
|
15
|
+
read-only views below, so they may appear unused to static analysis tools.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
PHASE_HISTORY_MAXLEN: int = 50
|
|
19
|
+
STOP_EARLY: dict[str, Any] = field(
|
|
20
|
+
default_factory=lambda: {
|
|
21
|
+
"enabled": False,
|
|
22
|
+
"window": 25,
|
|
23
|
+
"fraction": 0.90,
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
SIGMA: dict[str, Any] = field(
|
|
27
|
+
default_factory=lambda: {
|
|
28
|
+
"enabled": True,
|
|
29
|
+
"weight": "Si", # "Si" | "EPI" | "1"
|
|
30
|
+
"smooth": 0.0, # EMA sobre el vector global (0=off)
|
|
31
|
+
"history_key": "sigma_global",
|
|
32
|
+
"per_node": False,
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
TRACE: dict[str, Any] = field(
|
|
36
|
+
default_factory=lambda: {
|
|
37
|
+
"enabled": True,
|
|
38
|
+
"verbosity": "debug",
|
|
39
|
+
"history_key": "trace_meta",
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
METRICS: dict[str, Any] = field(
|
|
43
|
+
default_factory=lambda: {
|
|
44
|
+
"enabled": True,
|
|
45
|
+
"save_by_node": True,
|
|
46
|
+
"normalize_series": False,
|
|
47
|
+
"n_jobs": 1,
|
|
48
|
+
"verbosity": "debug",
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
GRAMMAR_CANON: dict[str, Any] = field(
|
|
52
|
+
default_factory=lambda: {
|
|
53
|
+
"enabled": True,
|
|
54
|
+
"zhir_requires_oz_window": 3,
|
|
55
|
+
"zhir_dnfr_min": 0.05,
|
|
56
|
+
"thol_min_len": 2,
|
|
57
|
+
"thol_max_len": 6,
|
|
58
|
+
"thol_close_dnfr": 0.15,
|
|
59
|
+
"si_high": 0.66,
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
COHERENCE: dict[str, Any] = field(
|
|
63
|
+
default_factory=lambda: {
|
|
64
|
+
"enabled": True,
|
|
65
|
+
"scope": "neighbors",
|
|
66
|
+
"weights": {"phase": 0.34, "epi": 0.33, "vf": 0.20, "si": 0.13},
|
|
67
|
+
"self_on_diag": True,
|
|
68
|
+
"store_mode": "sparse",
|
|
69
|
+
"threshold": 0.0,
|
|
70
|
+
"n_jobs": 1,
|
|
71
|
+
"history_key": "W_sparse",
|
|
72
|
+
"Wi_history_key": "W_i",
|
|
73
|
+
"stats_history_key": "W_stats",
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
DIAGNOSIS: dict[str, Any] = field(
|
|
77
|
+
default_factory=lambda: {
|
|
78
|
+
"enabled": True,
|
|
79
|
+
"window": 16,
|
|
80
|
+
"history_key": "nodal_diag",
|
|
81
|
+
"stable": {"Rloc_hi": 0.80, "dnfr_lo": 0.20, "persist": 3},
|
|
82
|
+
"dissonance": {"Rloc_lo": 0.40, "dnfr_hi": 0.50, "persist": 3},
|
|
83
|
+
"transition": {"persist": 2},
|
|
84
|
+
"compute_symmetry": True,
|
|
85
|
+
"include_typology": False,
|
|
86
|
+
"advice": {
|
|
87
|
+
"stable": ["Coherence", "Coupling", "Resonance"],
|
|
88
|
+
"transition": ["Transition", "Resonance", "Self-organisation"],
|
|
89
|
+
"dissonant": ["Silence", "Contraction", "Mutation"],
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
METRIC_DEFAULTS = asdict(MetricDefaults())
|
|
96
|
+
|
|
97
|
+
SIGMA = MappingProxyType(METRIC_DEFAULTS["SIGMA"])
|
|
98
|
+
TRACE = MappingProxyType(METRIC_DEFAULTS["TRACE"])
|
|
99
|
+
METRICS = MappingProxyType(METRIC_DEFAULTS["METRICS"])
|
|
100
|
+
GRAMMAR_CANON = MappingProxyType(METRIC_DEFAULTS["GRAMMAR_CANON"])
|
|
101
|
+
COHERENCE = MappingProxyType(METRIC_DEFAULTS["COHERENCE"])
|
|
102
|
+
DIAGNOSIS = MappingProxyType(METRIC_DEFAULTS["DIAGNOSIS"])
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
__all__: Any
|
|
4
|
+
|
|
5
|
+
def __getattr__(name: str) -> Any: ...
|
|
6
|
+
|
|
7
|
+
COHERENCE: Any
|
|
8
|
+
DIAGNOSIS: Any
|
|
9
|
+
GRAMMAR_CANON: Any
|
|
10
|
+
METRICS: Any
|
|
11
|
+
METRIC_DEFAULTS: Any
|
|
12
|
+
MappingProxyType: Any
|
|
13
|
+
MetricDefaults: Any
|
|
14
|
+
SIGMA: Any
|
|
15
|
+
TRACE: Any
|
|
16
|
+
annotations: Any
|
|
17
|
+
asdict: Any
|
|
18
|
+
dataclass: Any
|
|
19
|
+
field: Any
|
tnfr/constants_glyphs.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Backward compatibility shim for glyph constants."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
from .config.constants import * # noqa: F401,F403 - re-export legacy API
|
|
8
|
+
from .config.constants import __all__ as _CONFIG_ALL
|
|
9
|
+
|
|
10
|
+
warnings.warn(
|
|
11
|
+
"'tnfr.constants_glyphs' is deprecated; use 'tnfr.config.constants' instead",
|
|
12
|
+
DeprecationWarning,
|
|
13
|
+
stacklevel=2,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = _CONFIG_ALL
|