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/callback_utils.py
CHANGED
|
@@ -9,22 +9,20 @@ modify shared state.
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
from enum import Enum
|
|
12
|
+
import threading
|
|
13
|
+
import traceback
|
|
15
14
|
from collections import defaultdict, deque
|
|
16
|
-
from collections.abc import Callable,
|
|
15
|
+
from collections.abc import Callable, Iterable, Mapping
|
|
16
|
+
from enum import Enum
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
import networkx as nx
|
|
17
20
|
|
|
18
|
-
import traceback
|
|
19
|
-
import threading
|
|
20
|
-
from .logging_utils import get_logger
|
|
21
21
|
from .constants import DEFAULTS
|
|
22
22
|
from .locking import get_lock
|
|
23
|
-
|
|
24
23
|
from .trace import CallbackSpec
|
|
25
|
-
from .
|
|
26
|
-
|
|
27
|
-
import networkx as nx # type: ignore[import-untyped]
|
|
24
|
+
from .utils import get_logger, is_non_string_sequence
|
|
25
|
+
from .types import CallbackError
|
|
28
26
|
|
|
29
27
|
__all__ = (
|
|
30
28
|
"CallbackEvent",
|
|
@@ -42,6 +40,7 @@ class CallbackEvent(str, Enum):
|
|
|
42
40
|
BEFORE_STEP = "before_step"
|
|
43
41
|
AFTER_STEP = "after_step"
|
|
44
42
|
ON_REMESH = "on_remesh"
|
|
43
|
+
CACHE_METRICS = "cache_metrics"
|
|
45
44
|
|
|
46
45
|
|
|
47
46
|
class CallbackManager:
|
|
@@ -131,9 +130,7 @@ class CallbackManager:
|
|
|
131
130
|
cb_name = name or getattr(func, "__name__", None)
|
|
132
131
|
spec = CallbackSpec(cb_name, func)
|
|
133
132
|
existing_map = cbs[event]
|
|
134
|
-
strict = bool(
|
|
135
|
-
G.graph.get("CALLBACKS_STRICT", DEFAULTS["CALLBACKS_STRICT"])
|
|
136
|
-
)
|
|
133
|
+
strict = bool(G.graph.get("CALLBACKS_STRICT", DEFAULTS["CALLBACKS_STRICT"]))
|
|
137
134
|
key = _reconcile_callback(event, existing_map, spec, strict)
|
|
138
135
|
|
|
139
136
|
existing_map[key] = spec
|
|
@@ -152,9 +149,7 @@ class CallbackManager:
|
|
|
152
149
|
event = _normalize_event(event)
|
|
153
150
|
with self._lock:
|
|
154
151
|
cbs = dict(self._ensure_callbacks_nolock(G).get(event, {}))
|
|
155
|
-
strict = bool(
|
|
156
|
-
G.graph.get("CALLBACKS_STRICT", DEFAULTS["CALLBACKS_STRICT"])
|
|
157
|
-
)
|
|
152
|
+
strict = bool(G.graph.get("CALLBACKS_STRICT", DEFAULTS["CALLBACKS_STRICT"]))
|
|
158
153
|
if ctx is None:
|
|
159
154
|
ctx = {}
|
|
160
155
|
for spec in cbs.values():
|
|
@@ -185,17 +180,6 @@ Callback = Callable[["nx.Graph", dict[str, Any]], None]
|
|
|
185
180
|
CallbackRegistry = dict[str, dict[str, "CallbackSpec"]]
|
|
186
181
|
|
|
187
182
|
|
|
188
|
-
class CallbackError(TypedDict):
|
|
189
|
-
"""Metadata for a failed callback invocation."""
|
|
190
|
-
|
|
191
|
-
event: str
|
|
192
|
-
step: int | None
|
|
193
|
-
error: str
|
|
194
|
-
traceback: str
|
|
195
|
-
fn: str
|
|
196
|
-
name: str | None
|
|
197
|
-
|
|
198
|
-
|
|
199
183
|
def _func_id(fn: Callable[..., Any]) -> str:
|
|
200
184
|
"""Return a deterministic identifier for ``fn``.
|
|
201
185
|
|
|
@@ -211,9 +195,7 @@ def _func_id(fn: Callable[..., Any]) -> str:
|
|
|
211
195
|
return f"{module}.{qualname}"
|
|
212
196
|
|
|
213
197
|
|
|
214
|
-
def _validate_registry(
|
|
215
|
-
G: "nx.Graph", cbs: Any, dirty: set[str]
|
|
216
|
-
) -> CallbackRegistry:
|
|
198
|
+
def _validate_registry(G: "nx.Graph", cbs: Any, dirty: set[str]) -> CallbackRegistry:
|
|
217
199
|
"""Validate and normalise the callback registry.
|
|
218
200
|
|
|
219
201
|
``cbs`` is coerced to a ``defaultdict(dict)`` and any events listed in
|
|
@@ -246,13 +228,13 @@ def _validate_registry(
|
|
|
246
228
|
return cbs
|
|
247
229
|
|
|
248
230
|
|
|
249
|
-
|
|
250
|
-
|
|
251
231
|
def _normalize_callbacks(entries: Any) -> dict[str, CallbackSpec]:
|
|
252
232
|
"""Return ``entries`` normalised into a callback mapping."""
|
|
253
233
|
if isinstance(entries, Mapping):
|
|
254
234
|
entries_iter = entries.values()
|
|
255
|
-
elif isinstance(entries, Iterable) and not isinstance(
|
|
235
|
+
elif isinstance(entries, Iterable) and not isinstance(
|
|
236
|
+
entries, (str, bytes, bytearray)
|
|
237
|
+
):
|
|
256
238
|
entries_iter = entries
|
|
257
239
|
else:
|
|
258
240
|
return {}
|
|
@@ -328,7 +310,6 @@ def _normalize_callback_entry(entry: Any) -> "CallbackSpec | None":
|
|
|
328
310
|
return None
|
|
329
311
|
|
|
330
312
|
|
|
331
|
-
|
|
332
313
|
def _reconcile_callback(
|
|
333
314
|
event: str,
|
|
334
315
|
existing_map: dict[str, CallbackSpec],
|
|
@@ -383,6 +364,3 @@ def _reconcile_callback(
|
|
|
383
364
|
# ---------------------------------------------------------------------------
|
|
384
365
|
|
|
385
366
|
callback_manager = CallbackManager()
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
tnfr/callback_utils.pyi
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import threading
|
|
4
|
+
import traceback
|
|
5
|
+
from collections import defaultdict, deque
|
|
6
|
+
from collections.abc import Callable, Iterable, Mapping
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import networkx as nx
|
|
11
|
+
|
|
12
|
+
from .constants import DEFAULTS
|
|
13
|
+
from .locking import get_lock
|
|
14
|
+
from .trace import CallbackSpec
|
|
15
|
+
from .types import CallbackError
|
|
16
|
+
from .utils import get_logger, is_non_string_sequence
|
|
17
|
+
|
|
18
|
+
__all__ = (
|
|
19
|
+
"CallbackEvent",
|
|
20
|
+
"CallbackManager",
|
|
21
|
+
"callback_manager",
|
|
22
|
+
"CallbackError",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
logger: Any
|
|
26
|
+
|
|
27
|
+
class CallbackEvent(str, Enum):
|
|
28
|
+
BEFORE_STEP = "before_step"
|
|
29
|
+
AFTER_STEP = "after_step"
|
|
30
|
+
ON_REMESH = "on_remesh"
|
|
31
|
+
CACHE_METRICS = "cache_metrics"
|
|
32
|
+
|
|
33
|
+
Callback = Callable[[nx.Graph, dict[str, Any]], None]
|
|
34
|
+
CallbackRegistry = dict[str, dict[str, CallbackSpec]]
|
|
35
|
+
|
|
36
|
+
class CallbackManager:
|
|
37
|
+
def __init__(self) -> None: ...
|
|
38
|
+
def get_callback_error_limit(self) -> int: ...
|
|
39
|
+
def set_callback_error_limit(self, limit: int) -> int: ...
|
|
40
|
+
def register_callback(
|
|
41
|
+
self,
|
|
42
|
+
G: nx.Graph,
|
|
43
|
+
event: CallbackEvent | str,
|
|
44
|
+
func: Callback,
|
|
45
|
+
*,
|
|
46
|
+
name: str | None = ...,
|
|
47
|
+
) -> Callback: ...
|
|
48
|
+
def invoke_callbacks(
|
|
49
|
+
self,
|
|
50
|
+
G: nx.Graph,
|
|
51
|
+
event: CallbackEvent | str,
|
|
52
|
+
ctx: dict[str, Any] | None = ...,
|
|
53
|
+
) -> None: ...
|
|
54
|
+
def _record_callback_error(
|
|
55
|
+
self,
|
|
56
|
+
G: nx.Graph,
|
|
57
|
+
event: str,
|
|
58
|
+
ctx: dict[str, Any],
|
|
59
|
+
spec: CallbackSpec,
|
|
60
|
+
err: Exception,
|
|
61
|
+
) -> None: ...
|
|
62
|
+
def _ensure_callbacks_nolock(self, G: nx.Graph) -> CallbackRegistry: ...
|
|
63
|
+
def _ensure_callbacks(self, G: nx.Graph) -> CallbackRegistry: ...
|
|
64
|
+
|
|
65
|
+
callback_manager: CallbackManager
|
|
66
|
+
|
|
67
|
+
def _func_id(fn: Callable[..., Any]) -> str: ...
|
|
68
|
+
def _validate_registry(G: nx.Graph, cbs: Any, dirty: set[str]) -> CallbackRegistry: ...
|
|
69
|
+
def _normalize_callbacks(entries: Any) -> dict[str, CallbackSpec]: ...
|
|
70
|
+
def _normalize_event(event: CallbackEvent | str) -> str: ...
|
|
71
|
+
def _is_known_event(event: str) -> bool: ...
|
|
72
|
+
def _ensure_known_event(event: str) -> None: ...
|
|
73
|
+
def _normalize_callback_entry(entry: Any) -> CallbackSpec | None: ...
|
|
74
|
+
def _reconcile_callback(
|
|
75
|
+
event: str,
|
|
76
|
+
existing_map: dict[str, CallbackSpec],
|
|
77
|
+
spec: CallbackSpec,
|
|
78
|
+
strict: bool,
|
|
79
|
+
) -> str: ...
|
tnfr/cli/__init__.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""Command-line interface entry points for TNFR."""
|
|
2
|
+
|
|
1
3
|
from __future__ import annotations
|
|
2
4
|
|
|
3
5
|
import argparse
|
|
@@ -5,25 +7,27 @@ import logging
|
|
|
5
7
|
import sys
|
|
6
8
|
from typing import Optional
|
|
7
9
|
|
|
10
|
+
from .. import __version__
|
|
11
|
+
from ..utils import _configure_root, get_logger
|
|
8
12
|
from .arguments import (
|
|
13
|
+
_add_metrics_parser,
|
|
14
|
+
_add_profile_parser,
|
|
15
|
+
_add_profile_pipeline_parser,
|
|
16
|
+
_add_run_parser,
|
|
17
|
+
_add_sequence_parser,
|
|
18
|
+
add_canon_toggle,
|
|
9
19
|
add_common_args,
|
|
10
20
|
add_grammar_args,
|
|
11
21
|
add_grammar_selector_args,
|
|
12
22
|
add_history_export_args,
|
|
13
|
-
add_canon_toggle,
|
|
14
|
-
_add_run_parser,
|
|
15
|
-
_add_sequence_parser,
|
|
16
|
-
_add_metrics_parser,
|
|
17
23
|
)
|
|
18
24
|
from .execution import (
|
|
19
|
-
build_basic_graph,
|
|
20
25
|
apply_cli_config,
|
|
26
|
+
build_basic_graph,
|
|
21
27
|
register_callbacks_and_observer,
|
|
22
|
-
run_program,
|
|
23
28
|
resolve_program,
|
|
29
|
+
run_program,
|
|
24
30
|
)
|
|
25
|
-
from ..logging_utils import get_logger
|
|
26
|
-
from .. import __version__
|
|
27
31
|
|
|
28
32
|
logger = get_logger(__name__)
|
|
29
33
|
|
|
@@ -43,27 +47,43 @@ __all__ = (
|
|
|
43
47
|
|
|
44
48
|
|
|
45
49
|
def main(argv: Optional[list[str]] = None) -> int:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
)
|
|
50
|
+
"""Entry point for the ``tnfr`` CLI returning the exit status."""
|
|
51
|
+
|
|
52
|
+
_configure_root()
|
|
53
|
+
|
|
54
|
+
root = logging.getLogger()
|
|
55
|
+
root.setLevel(logging.INFO)
|
|
56
|
+
|
|
57
|
+
formatter = logging.Formatter("%(message)s")
|
|
58
|
+
for handler in list(root.handlers):
|
|
59
|
+
root.removeHandler(handler)
|
|
60
|
+
|
|
61
|
+
handler = logging.StreamHandler(stream=sys.stdout)
|
|
62
|
+
handler.setLevel(logging.INFO)
|
|
63
|
+
handler.setFormatter(formatter)
|
|
64
|
+
root.addHandler(handler)
|
|
49
65
|
|
|
50
66
|
p = argparse.ArgumentParser(
|
|
51
67
|
prog="tnfr",
|
|
52
68
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
53
69
|
epilog=(
|
|
54
|
-
"
|
|
55
|
-
"
|
|
70
|
+
"Example: tnfr sequence --sequence-file sequence.json\n"
|
|
71
|
+
"sequence.json:\n"
|
|
56
72
|
'[\n {"WAIT": 1},\n {"TARGET": "A"}\n]'
|
|
57
73
|
),
|
|
58
74
|
)
|
|
59
75
|
p.add_argument(
|
|
60
|
-
"--version",
|
|
76
|
+
"--version",
|
|
77
|
+
action="store_true",
|
|
78
|
+
help=("show the actual version and exit (reads pyproject.toml in development)"),
|
|
61
79
|
)
|
|
62
80
|
sub = p.add_subparsers(dest="cmd")
|
|
63
81
|
|
|
64
82
|
_add_run_parser(sub)
|
|
65
83
|
_add_sequence_parser(sub)
|
|
66
84
|
_add_metrics_parser(sub)
|
|
85
|
+
_add_profile_parser(sub)
|
|
86
|
+
_add_profile_pipeline_parser(sub)
|
|
67
87
|
|
|
68
88
|
args = p.parse_args(argv)
|
|
69
89
|
if args.version:
|
tnfr/cli/__init__.pyi
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from ..types import ProgramTokens, TNFRGraph
|
|
7
|
+
|
|
8
|
+
__all__: tuple[str, ...]
|
|
9
|
+
|
|
10
|
+
def main(argv: Optional[list[str]] = None) -> int: ...
|
|
11
|
+
def add_common_args(parser: argparse.ArgumentParser) -> None: ...
|
|
12
|
+
def add_grammar_args(parser: argparse.ArgumentParser) -> None: ...
|
|
13
|
+
def add_grammar_selector_args(parser: argparse.ArgumentParser) -> None: ...
|
|
14
|
+
def add_history_export_args(parser: argparse.ArgumentParser) -> None: ...
|
|
15
|
+
def add_canon_toggle(parser: argparse.ArgumentParser) -> None: ...
|
|
16
|
+
def build_basic_graph(args: argparse.Namespace) -> TNFRGraph: ...
|
|
17
|
+
def apply_cli_config(G: TNFRGraph, args: argparse.Namespace) -> None: ...
|
|
18
|
+
def register_callbacks_and_observer(G: TNFRGraph) -> None: ...
|
|
19
|
+
def resolve_program(
|
|
20
|
+
args: argparse.Namespace, default: Optional[ProgramTokens] = None
|
|
21
|
+
) -> Optional[ProgramTokens]: ...
|
|
22
|
+
def run_program(
|
|
23
|
+
G: Optional[TNFRGraph],
|
|
24
|
+
program: Optional[ProgramTokens],
|
|
25
|
+
args: argparse.Namespace,
|
|
26
|
+
) -> TNFRGraph: ...
|
tnfr/cli/arguments.py
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
|
+
"""Argument parser helpers shared across TNFR CLI commands."""
|
|
2
|
+
|
|
1
3
|
from __future__ import annotations
|
|
2
4
|
|
|
3
5
|
import argparse
|
|
4
|
-
from
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Iterable
|
|
5
8
|
|
|
9
|
+
from ..config.presets import PREFERRED_PRESET_NAMES
|
|
6
10
|
from ..gamma import GAMMA_REGISTRY
|
|
11
|
+
from ..telemetry.verbosity import TELEMETRY_VERBOSITY_LEVELS
|
|
12
|
+
from ..types import ArgSpec
|
|
7
13
|
from .utils import spec
|
|
8
14
|
|
|
15
|
+
_PRESET_HELP = "Available presets: {}.".format(
|
|
16
|
+
", ".join(PREFERRED_PRESET_NAMES),
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
TELEMETRY_VERBOSITY_CHOICES = TELEMETRY_VERBOSITY_LEVELS
|
|
9
20
|
|
|
10
|
-
|
|
21
|
+
|
|
22
|
+
GRAMMAR_ARG_SPECS: tuple[ArgSpec, ...] = (
|
|
11
23
|
spec("--grammar.enabled", action=argparse.BooleanOptionalAction),
|
|
12
24
|
spec("--grammar.zhir_requires_oz_window", type=int),
|
|
13
25
|
spec("--grammar.zhir_dnfr_min", type=float),
|
|
@@ -19,25 +31,35 @@ GRAMMAR_ARG_SPECS = (
|
|
|
19
31
|
)
|
|
20
32
|
|
|
21
33
|
|
|
22
|
-
#
|
|
23
|
-
HISTORY_ARG_SPECS = (
|
|
34
|
+
# History export/save specifications
|
|
35
|
+
HISTORY_ARG_SPECS: tuple[ArgSpec, ...] = (
|
|
24
36
|
spec("--save-history", type=str),
|
|
25
37
|
spec("--export-history-base", type=str),
|
|
26
38
|
spec("--export-format", choices=["csv", "json"], default="json"),
|
|
27
39
|
)
|
|
28
40
|
|
|
29
41
|
|
|
30
|
-
#
|
|
31
|
-
COMMON_ARG_SPECS = (
|
|
42
|
+
# Arguments shared by CLI subcommands
|
|
43
|
+
COMMON_ARG_SPECS: tuple[ArgSpec, ...] = (
|
|
32
44
|
spec("--nodes", type=int, default=24),
|
|
33
45
|
spec("--topology", choices=["ring", "complete", "erdos"], default="ring"),
|
|
34
46
|
spec("--seed", type=int, default=1),
|
|
35
47
|
spec(
|
|
36
48
|
"--p",
|
|
37
49
|
type=float,
|
|
38
|
-
help="
|
|
50
|
+
help="Edge probability when topology=erdos",
|
|
51
|
+
),
|
|
52
|
+
spec("--observer", action="store_true", help="Attach standard observer"),
|
|
53
|
+
spec(
|
|
54
|
+
"--trace-verbosity",
|
|
55
|
+
choices=TELEMETRY_VERBOSITY_CHOICES,
|
|
56
|
+
help="Select the trace capture preset",
|
|
57
|
+
),
|
|
58
|
+
spec(
|
|
59
|
+
"--metrics-verbosity",
|
|
60
|
+
choices=TELEMETRY_VERBOSITY_CHOICES,
|
|
61
|
+
help="Select the metrics capture preset",
|
|
39
62
|
),
|
|
40
|
-
spec("--observer", action="store_true", help="Adjunta observador estándar"),
|
|
41
63
|
spec("--config", type=str),
|
|
42
64
|
spec("--dt", type=float),
|
|
43
65
|
spec("--integrator", choices=["euler", "rk4"]),
|
|
@@ -45,10 +67,13 @@ COMMON_ARG_SPECS = (
|
|
|
45
67
|
spec("--gamma-type", choices=list(GAMMA_REGISTRY.keys()), default="none"),
|
|
46
68
|
spec("--gamma-beta", type=float, default=0.0),
|
|
47
69
|
spec("--gamma-R0", type=float, default=0.0),
|
|
70
|
+
spec("--um-candidate-count", type=int),
|
|
71
|
+
spec("--stop-early-window", type=int),
|
|
72
|
+
spec("--stop-early-fraction", type=float),
|
|
48
73
|
)
|
|
49
74
|
|
|
50
75
|
|
|
51
|
-
def add_arg_specs(parser: argparse._ActionsContainer, specs) -> None:
|
|
76
|
+
def add_arg_specs(parser: argparse._ActionsContainer, specs: Iterable[ArgSpec]) -> None:
|
|
52
77
|
"""Register arguments from ``specs`` on ``parser``."""
|
|
53
78
|
for opt, kwargs in specs:
|
|
54
79
|
parser.add_argument(opt, **kwargs)
|
|
@@ -77,9 +102,7 @@ def add_grammar_args(parser: argparse.ArgumentParser) -> None:
|
|
|
77
102
|
def add_grammar_selector_args(parser: argparse.ArgumentParser) -> None:
|
|
78
103
|
"""Add grammar options and glyph selector."""
|
|
79
104
|
add_grammar_args(parser)
|
|
80
|
-
parser.add_argument(
|
|
81
|
-
"--selector", choices=["basic", "param"], default="basic"
|
|
82
|
-
)
|
|
105
|
+
parser.add_argument("--selector", choices=["basic", "param"], default="basic")
|
|
83
106
|
|
|
84
107
|
|
|
85
108
|
def add_history_export_args(parser: argparse.ArgumentParser) -> None:
|
|
@@ -94,26 +117,45 @@ def add_canon_toggle(parser: argparse.ArgumentParser) -> None:
|
|
|
94
117
|
dest="grammar_canon",
|
|
95
118
|
action="store_false",
|
|
96
119
|
default=True,
|
|
97
|
-
help="
|
|
120
|
+
help="Disable canonical grammar",
|
|
98
121
|
)
|
|
99
122
|
|
|
100
123
|
|
|
101
124
|
def _add_run_parser(sub: argparse._SubParsersAction) -> None:
|
|
102
125
|
"""Configure the ``run`` subcommand."""
|
|
103
|
-
|
|
126
|
+
|
|
127
|
+
from .execution import DEFAULT_SUMMARY_SERIES_LIMIT, cmd_run
|
|
104
128
|
|
|
105
129
|
p_run = sub.add_parser(
|
|
106
130
|
"run",
|
|
107
|
-
help=(
|
|
108
|
-
"Correr escenario libre o preset y opcionalmente exportar history"
|
|
109
|
-
),
|
|
131
|
+
help=("Run a free scenario or preset and optionally export history"),
|
|
110
132
|
)
|
|
111
133
|
add_common_args(p_run)
|
|
112
134
|
p_run.add_argument("--steps", type=int, default=100)
|
|
135
|
+
p_run.add_argument(
|
|
136
|
+
"--use-Si",
|
|
137
|
+
dest="use_Si",
|
|
138
|
+
action=argparse.BooleanOptionalAction,
|
|
139
|
+
default=None,
|
|
140
|
+
help="Recompute the Sense Index during the run (use --no-use-Si to disable)",
|
|
141
|
+
)
|
|
142
|
+
p_run.add_argument(
|
|
143
|
+
"--apply-glyphs",
|
|
144
|
+
dest="apply_glyphs",
|
|
145
|
+
action=argparse.BooleanOptionalAction,
|
|
146
|
+
default=None,
|
|
147
|
+
help="Apply glyphs at every step (use --no-apply-glyphs to disable)",
|
|
148
|
+
)
|
|
149
|
+
p_run.add_argument(
|
|
150
|
+
"--dnfr-n-jobs",
|
|
151
|
+
dest="dnfr_n_jobs",
|
|
152
|
+
type=int,
|
|
153
|
+
help="Override ΔNFR parallel jobs forwarded to the runtime",
|
|
154
|
+
)
|
|
113
155
|
add_canon_toggle(p_run)
|
|
114
156
|
add_grammar_selector_args(p_run)
|
|
115
157
|
add_history_export_args(p_run)
|
|
116
|
-
p_run.add_argument("--preset", type=str, default=None)
|
|
158
|
+
p_run.add_argument("--preset", type=str, default=None, help=_PRESET_HELP)
|
|
117
159
|
p_run.add_argument("--sequence-file", type=str, default=None)
|
|
118
160
|
p_run.add_argument("--summary", action="store_true")
|
|
119
161
|
p_run.add_argument(
|
|
@@ -121,10 +163,68 @@ def _add_run_parser(sub: argparse._SubParsersAction) -> None:
|
|
|
121
163
|
type=int,
|
|
122
164
|
default=DEFAULT_SUMMARY_SERIES_LIMIT,
|
|
123
165
|
help=(
|
|
124
|
-
"
|
|
125
|
-
"
|
|
166
|
+
"Maximum number of samples per series in the summary (<=0 to"
|
|
167
|
+
" disable trimming)"
|
|
168
|
+
),
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
math_group = p_run.add_argument_group("Mathematical dynamics")
|
|
172
|
+
math_group.add_argument(
|
|
173
|
+
"--math-engine",
|
|
174
|
+
action=argparse.BooleanOptionalAction,
|
|
175
|
+
default=False,
|
|
176
|
+
help=(
|
|
177
|
+
"Enable the spectral mathematical dynamics engine to project nodes"
|
|
178
|
+
" onto Hilbert space vectors and validate norm, coherence and"
|
|
179
|
+
" structural frequency invariants"
|
|
180
|
+
),
|
|
181
|
+
)
|
|
182
|
+
math_group.add_argument(
|
|
183
|
+
"--math-dimension",
|
|
184
|
+
type=int,
|
|
185
|
+
help="Hilbert space dimension to use when the math engine is enabled",
|
|
186
|
+
)
|
|
187
|
+
math_group.add_argument(
|
|
188
|
+
"--math-coherence-spectrum",
|
|
189
|
+
type=float,
|
|
190
|
+
nargs="+",
|
|
191
|
+
metavar="λ",
|
|
192
|
+
help=(
|
|
193
|
+
"Eigenvalues for the coherence operator (defaults to a flat"
|
|
194
|
+
" spectrum when omitted)"
|
|
195
|
+
),
|
|
196
|
+
)
|
|
197
|
+
math_group.add_argument(
|
|
198
|
+
"--math-coherence-c-min",
|
|
199
|
+
type=float,
|
|
200
|
+
help="Explicit coherence floor C_min for the operator",
|
|
201
|
+
)
|
|
202
|
+
math_group.add_argument(
|
|
203
|
+
"--math-coherence-threshold",
|
|
204
|
+
type=float,
|
|
205
|
+
help="Coherence expectation threshold enforced during validation",
|
|
206
|
+
)
|
|
207
|
+
math_group.add_argument(
|
|
208
|
+
"--math-frequency-diagonal",
|
|
209
|
+
type=float,
|
|
210
|
+
nargs="+",
|
|
211
|
+
metavar="ν",
|
|
212
|
+
help=(
|
|
213
|
+
"Diagonal entries for the structural frequency operator"
|
|
214
|
+
" (defaults to the identity spectrum)"
|
|
126
215
|
),
|
|
127
216
|
)
|
|
217
|
+
math_group.add_argument(
|
|
218
|
+
"--math-generator-diagonal",
|
|
219
|
+
type=float,
|
|
220
|
+
nargs="+",
|
|
221
|
+
metavar="ω",
|
|
222
|
+
help=(
|
|
223
|
+
"Diagonal ΔNFR generator used by the mathematical dynamics"
|
|
224
|
+
" engine (defaults to the null generator)"
|
|
225
|
+
),
|
|
226
|
+
)
|
|
227
|
+
|
|
128
228
|
p_run.set_defaults(func=cmd_run)
|
|
129
229
|
|
|
130
230
|
|
|
@@ -134,10 +234,10 @@ def _add_sequence_parser(sub: argparse._SubParsersAction) -> None:
|
|
|
134
234
|
|
|
135
235
|
p_seq = sub.add_parser(
|
|
136
236
|
"sequence",
|
|
137
|
-
help="
|
|
237
|
+
help="Execute a sequence (preset or YAML/JSON)",
|
|
138
238
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
139
239
|
epilog=(
|
|
140
|
-
"
|
|
240
|
+
"JSON sequence example:\n"
|
|
141
241
|
"[\n"
|
|
142
242
|
' "A",\n'
|
|
143
243
|
' {"WAIT": 1},\n'
|
|
@@ -146,7 +246,7 @@ def _add_sequence_parser(sub: argparse._SubParsersAction) -> None:
|
|
|
146
246
|
),
|
|
147
247
|
)
|
|
148
248
|
add_common_args(p_seq)
|
|
149
|
-
p_seq.add_argument("--preset", type=str, default=None)
|
|
249
|
+
p_seq.add_argument("--preset", type=str, default=None, help=_PRESET_HELP)
|
|
150
250
|
p_seq.add_argument("--sequence-file", type=str, default=None)
|
|
151
251
|
add_history_export_args(p_seq)
|
|
152
252
|
add_grammar_args(p_seq)
|
|
@@ -157,9 +257,7 @@ def _add_metrics_parser(sub: argparse._SubParsersAction) -> None:
|
|
|
157
257
|
"""Configure the ``metrics`` subcommand."""
|
|
158
258
|
from .execution import cmd_metrics
|
|
159
259
|
|
|
160
|
-
p_met = sub.add_parser(
|
|
161
|
-
"metrics", help="Correr breve y volcar métricas clave"
|
|
162
|
-
)
|
|
260
|
+
p_met = sub.add_parser("metrics", help="Run briefly and export key metrics")
|
|
163
261
|
add_common_args(p_met)
|
|
164
262
|
p_met.add_argument("--steps", type=int, default=None)
|
|
165
263
|
add_canon_toggle(p_met)
|
|
@@ -170,8 +268,93 @@ def _add_metrics_parser(sub: argparse._SubParsersAction) -> None:
|
|
|
170
268
|
type=int,
|
|
171
269
|
default=None,
|
|
172
270
|
help=(
|
|
173
|
-
"
|
|
174
|
-
"
|
|
271
|
+
"Maximum number of samples per series in the summary (<=0 to"
|
|
272
|
+
" disable trimming)"
|
|
175
273
|
),
|
|
176
274
|
)
|
|
177
275
|
p_met.set_defaults(func=cmd_metrics)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def _add_profile_parser(sub: argparse._SubParsersAction) -> None:
|
|
279
|
+
"""Configure the ``profile-si`` subcommand."""
|
|
280
|
+
|
|
281
|
+
from .execution import cmd_profile_si
|
|
282
|
+
|
|
283
|
+
p_prof = sub.add_parser(
|
|
284
|
+
"profile-si",
|
|
285
|
+
help="Profile compute_Si with and without NumPy",
|
|
286
|
+
)
|
|
287
|
+
p_prof.add_argument("--nodes", type=int, default=240)
|
|
288
|
+
p_prof.add_argument("--chord-step", type=int, default=7)
|
|
289
|
+
p_prof.add_argument("--loops", type=int, default=5)
|
|
290
|
+
p_prof.add_argument("--output-dir", type=Path, default=Path("profiles"))
|
|
291
|
+
p_prof.add_argument("--format", choices=("pstats", "json"), default="pstats")
|
|
292
|
+
p_prof.add_argument("--sort", choices=("cumtime", "tottime"), default="cumtime")
|
|
293
|
+
p_prof.set_defaults(func=cmd_profile_si)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def _add_profile_pipeline_parser(sub: argparse._SubParsersAction) -> None:
|
|
297
|
+
"""Configure the ``profile-pipeline`` subcommand."""
|
|
298
|
+
|
|
299
|
+
from .execution import cmd_profile_pipeline
|
|
300
|
+
|
|
301
|
+
p_profile = sub.add_parser(
|
|
302
|
+
"profile-pipeline",
|
|
303
|
+
help="Profile the Sense Index + ΔNFR pipeline",
|
|
304
|
+
)
|
|
305
|
+
p_profile.add_argument("--nodes", type=int, default=240, help="Number of nodes")
|
|
306
|
+
p_profile.add_argument(
|
|
307
|
+
"--edge-probability",
|
|
308
|
+
type=float,
|
|
309
|
+
default=0.32,
|
|
310
|
+
help="Probability passed to the Erdos-Renyi generator",
|
|
311
|
+
)
|
|
312
|
+
p_profile.add_argument(
|
|
313
|
+
"--loops",
|
|
314
|
+
type=int,
|
|
315
|
+
default=5,
|
|
316
|
+
help="How many times to execute the pipeline inside the profiler",
|
|
317
|
+
)
|
|
318
|
+
p_profile.add_argument(
|
|
319
|
+
"--seed",
|
|
320
|
+
type=int,
|
|
321
|
+
default=42,
|
|
322
|
+
help="Random seed used when generating the graph",
|
|
323
|
+
)
|
|
324
|
+
p_profile.add_argument(
|
|
325
|
+
"--output-dir",
|
|
326
|
+
type=Path,
|
|
327
|
+
default=Path("profiles"),
|
|
328
|
+
help="Directory where profiling artefacts will be written",
|
|
329
|
+
)
|
|
330
|
+
p_profile.add_argument(
|
|
331
|
+
"--sort",
|
|
332
|
+
choices=("cumtime", "tottime"),
|
|
333
|
+
default="cumtime",
|
|
334
|
+
help="Sort order applied to profiling rows",
|
|
335
|
+
)
|
|
336
|
+
p_profile.add_argument(
|
|
337
|
+
"--si-chunk-sizes",
|
|
338
|
+
nargs="+",
|
|
339
|
+
metavar="SIZE",
|
|
340
|
+
help="Chunk sizes forwarded to G.graph['SI_CHUNK_SIZE']; use 'auto' for heuristics",
|
|
341
|
+
)
|
|
342
|
+
p_profile.add_argument(
|
|
343
|
+
"--dnfr-chunk-sizes",
|
|
344
|
+
nargs="+",
|
|
345
|
+
metavar="SIZE",
|
|
346
|
+
help="Chunk sizes forwarded to G.graph['DNFR_CHUNK_SIZE']; use 'auto' for heuristics",
|
|
347
|
+
)
|
|
348
|
+
p_profile.add_argument(
|
|
349
|
+
"--si-workers",
|
|
350
|
+
nargs="+",
|
|
351
|
+
metavar="COUNT",
|
|
352
|
+
help="Worker counts forwarded to G.graph['SI_N_JOBS']; use 'auto' for serial runs",
|
|
353
|
+
)
|
|
354
|
+
p_profile.add_argument(
|
|
355
|
+
"--dnfr-workers",
|
|
356
|
+
nargs="+",
|
|
357
|
+
metavar="COUNT",
|
|
358
|
+
help="Worker counts forwarded to G.graph['DNFR_N_JOBS']; use 'auto' for defaults",
|
|
359
|
+
)
|
|
360
|
+
p_profile.set_defaults(func=cmd_profile_pipeline)
|
tnfr/cli/arguments.pyi
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from typing import Any, Iterable
|
|
5
|
+
|
|
6
|
+
from ..gamma import GAMMA_REGISTRY
|
|
7
|
+
from ..types import ArgSpec
|
|
8
|
+
from .utils import spec
|
|
9
|
+
|
|
10
|
+
GRAMMAR_ARG_SPECS: tuple[ArgSpec, ...]
|
|
11
|
+
HISTORY_ARG_SPECS: tuple[ArgSpec, ...]
|
|
12
|
+
COMMON_ARG_SPECS: tuple[ArgSpec, ...]
|
|
13
|
+
|
|
14
|
+
def add_arg_specs(
|
|
15
|
+
parser: argparse._ActionsContainer, specs: Iterable[ArgSpec]
|
|
16
|
+
) -> None: ...
|
|
17
|
+
def _args_to_dict(args: argparse.Namespace, prefix: str) -> dict[str, Any]: ...
|
|
18
|
+
def add_common_args(parser: argparse.ArgumentParser) -> None: ...
|
|
19
|
+
def add_grammar_args(parser: argparse.ArgumentParser) -> None: ...
|
|
20
|
+
def add_grammar_selector_args(parser: argparse.ArgumentParser) -> None: ...
|
|
21
|
+
def add_history_export_args(parser: argparse.ArgumentParser) -> None: ...
|
|
22
|
+
def add_canon_toggle(parser: argparse.ArgumentParser) -> None: ...
|
|
23
|
+
def _add_run_parser(sub: argparse._SubParsersAction) -> None: ...
|
|
24
|
+
def _add_sequence_parser(sub: argparse._SubParsersAction) -> None: ...
|
|
25
|
+
def _add_metrics_parser(sub: argparse._SubParsersAction) -> None: ...
|
|
26
|
+
def _add_profile_parser(sub: argparse._SubParsersAction) -> None: ...
|
|
27
|
+
def _add_profile_pipeline_parser(sub: argparse._SubParsersAction) -> None: ...
|