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/dynamics/dnfr.pyi
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
3
|
from tnfr.types import DeltaNFRHook, TNFRGraph
|
|
4
|
+
from tnfr.utils.cache import DnfrCache as DnfrCache
|
|
4
5
|
|
|
5
6
|
__all__: tuple[str, ...]
|
|
6
7
|
|
|
@@ -10,17 +11,9 @@ def default_compute_delta_nfr(
|
|
|
10
11
|
cache_size: int | None = ...,
|
|
11
12
|
n_jobs: int | None = ...,
|
|
12
13
|
) -> None: ...
|
|
13
|
-
|
|
14
|
-
|
|
15
14
|
def dnfr_epi_vf_mixed(G: TNFRGraph, *, n_jobs: int | None = ...) -> None: ...
|
|
16
|
-
|
|
17
|
-
|
|
18
15
|
def dnfr_laplacian(G: TNFRGraph, *, n_jobs: int | None = ...) -> None: ...
|
|
19
|
-
|
|
20
|
-
|
|
21
16
|
def dnfr_phase_only(G: TNFRGraph, *, n_jobs: int | None = ...) -> None: ...
|
|
22
|
-
|
|
23
|
-
|
|
24
17
|
def set_delta_nfr_hook(
|
|
25
18
|
G: TNFRGraph,
|
|
26
19
|
func: DeltaNFRHook,
|
|
@@ -28,6 +21,4 @@ def set_delta_nfr_hook(
|
|
|
28
21
|
name: str | None = ...,
|
|
29
22
|
note: str | None = ...,
|
|
30
23
|
) -> None: ...
|
|
31
|
-
|
|
32
|
-
|
|
33
24
|
def __getattr__(name: str) -> Any: ...
|
tnfr/dynamics/integrators.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""Canonical ΔNFR integrators driving TNFR runtime evolution."""
|
|
2
|
+
|
|
1
3
|
from __future__ import annotations
|
|
2
4
|
|
|
3
5
|
import math
|
|
@@ -9,22 +11,20 @@ from typing import Any, Literal, cast
|
|
|
9
11
|
|
|
10
12
|
import networkx as nx
|
|
11
13
|
|
|
12
|
-
from ..
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
from .._compat import TypeAlias
|
|
15
|
+
from ..alias import collect_attr, get_attr, get_attr_str, set_attr, set_attr_str
|
|
16
|
+
from ..constants import DEFAULTS
|
|
17
|
+
from ..constants.aliases import (
|
|
18
|
+
ALIAS_D2EPI,
|
|
19
|
+
ALIAS_DEPI,
|
|
20
|
+
ALIAS_DNFR,
|
|
21
|
+
ALIAS_EPI,
|
|
22
|
+
ALIAS_EPI_KIND,
|
|
23
|
+
ALIAS_VF,
|
|
15
24
|
)
|
|
16
25
|
from ..gamma import _get_gamma_spec, eval_gamma
|
|
17
|
-
from ..alias import collect_attr, get_attr, get_attr_str, set_attr, set_attr_str
|
|
18
|
-
from ..utils import get_numpy
|
|
19
26
|
from ..types import NodeId, TNFRGraph
|
|
20
|
-
from ..
|
|
21
|
-
|
|
22
|
-
ALIAS_VF = get_aliases("VF")
|
|
23
|
-
ALIAS_DNFR = get_aliases("DNFR")
|
|
24
|
-
ALIAS_DEPI = get_aliases("DEPI")
|
|
25
|
-
ALIAS_EPI = get_aliases("EPI")
|
|
26
|
-
ALIAS_EPI_KIND = get_aliases("EPI_KIND")
|
|
27
|
-
ALIAS_D2EPI = get_aliases("D2EPI")
|
|
27
|
+
from ..utils import get_numpy, resolve_chunk_size
|
|
28
28
|
|
|
29
29
|
__all__ = (
|
|
30
30
|
"AbstractIntegrator",
|
|
@@ -63,9 +63,7 @@ def _gamma_worker(task: tuple[list[NodeId], float]) -> list[tuple[NodeId, float]
|
|
|
63
63
|
chunk, t = task
|
|
64
64
|
if _PARALLEL_GRAPH is None:
|
|
65
65
|
raise RuntimeError("Parallel Γ worker initialised without graph reference")
|
|
66
|
-
return [
|
|
67
|
-
(node, float(eval_gamma(_PARALLEL_GRAPH, node, t))) for node in chunk
|
|
68
|
-
]
|
|
66
|
+
return [(node, float(eval_gamma(_PARALLEL_GRAPH, node, t))) for node in chunk]
|
|
69
67
|
|
|
70
68
|
|
|
71
69
|
def _normalise_jobs(n_jobs: int | None, total: int) -> int | None:
|
|
@@ -86,7 +84,7 @@ def _chunk_nodes(nodes: list[NodeId], chunk_size: int) -> Iterable[list[NodeId]]
|
|
|
86
84
|
"""Yield deterministic chunks from ``nodes`` respecting insertion order."""
|
|
87
85
|
|
|
88
86
|
for idx in range(0, len(nodes), chunk_size):
|
|
89
|
-
yield nodes[idx:idx + chunk_size]
|
|
87
|
+
yield nodes[idx : idx + chunk_size]
|
|
90
88
|
|
|
91
89
|
|
|
92
90
|
def _apply_increment_chunk(
|
|
@@ -127,7 +125,12 @@ def _evaluate_gamma_map(
|
|
|
127
125
|
if workers is None:
|
|
128
126
|
return {n: float(eval_gamma(G, n, t)) for n in nodes}
|
|
129
127
|
|
|
130
|
-
|
|
128
|
+
approx_chunk = math.ceil(len(nodes) / (workers * 4)) if workers > 0 else None
|
|
129
|
+
chunk_size = resolve_chunk_size(
|
|
130
|
+
approx_chunk,
|
|
131
|
+
len(nodes),
|
|
132
|
+
minimum=1,
|
|
133
|
+
)
|
|
131
134
|
mp_ctx = get_context("spawn")
|
|
132
135
|
tasks = ((chunk, t) for chunk in _chunk_nodes(nodes, chunk_size))
|
|
133
136
|
|
|
@@ -153,9 +156,16 @@ def prepare_integration_params(
|
|
|
153
156
|
) -> tuple[float, int, float, Literal["euler", "rk4"]]:
|
|
154
157
|
"""Validate and normalise ``dt``, ``t`` and ``method`` for integration.
|
|
155
158
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
The function raises :class:`TypeError` when ``dt`` cannot be coerced to a
|
|
160
|
+
number, :class:`ValueError` if ``dt`` is negative, and another
|
|
161
|
+
:class:`ValueError` when an unsupported method is requested. When ``dt``
|
|
162
|
+
exceeds a positive ``DT_MIN`` stored on ``G`` the span is deterministically
|
|
163
|
+
subdivided into integer steps so that the resulting ``dt_step`` never falls
|
|
164
|
+
below that minimum threshold.
|
|
165
|
+
|
|
166
|
+
Returns ``(dt_step, steps, t0, method)`` where ``dt_step`` is the effective
|
|
167
|
+
step, ``steps`` the number of substeps and ``t0`` the prepared initial
|
|
168
|
+
time.
|
|
159
169
|
"""
|
|
160
170
|
if dt is None:
|
|
161
171
|
dt = float(G.graph.get("DT", DEFAULTS["DT"]))
|
|
@@ -173,20 +183,19 @@ def prepare_integration_params(
|
|
|
173
183
|
|
|
174
184
|
method_value = (
|
|
175
185
|
method
|
|
176
|
-
or G.graph.get(
|
|
177
|
-
"INTEGRATOR_METHOD", DEFAULTS.get("INTEGRATOR_METHOD", "euler")
|
|
178
|
-
)
|
|
186
|
+
or G.graph.get("INTEGRATOR_METHOD", DEFAULTS.get("INTEGRATOR_METHOD", "euler"))
|
|
179
187
|
).lower()
|
|
180
188
|
if method_value not in ("euler", "rk4"):
|
|
181
189
|
raise ValueError("method must be 'euler' or 'rk4'")
|
|
182
190
|
|
|
183
191
|
dt_min = float(G.graph.get("DT_MIN", DEFAULTS.get("DT_MIN", 0.0)))
|
|
192
|
+
steps = 1
|
|
184
193
|
if dt_min > 0 and dt > dt_min:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
steps
|
|
188
|
-
|
|
189
|
-
dt_step = dt / steps
|
|
194
|
+
ratio = dt / dt_min
|
|
195
|
+
steps = max(1, int(math.floor(ratio + 1e-12)))
|
|
196
|
+
if dt / steps < dt_min:
|
|
197
|
+
steps = int(math.ceil(ratio))
|
|
198
|
+
dt_step = dt / steps if steps else 0.0
|
|
190
199
|
|
|
191
200
|
return dt_step, steps, t, cast(Literal["euler", "rk4"], method_value)
|
|
192
201
|
|
|
@@ -263,7 +272,12 @@ def _apply_increments(
|
|
|
263
272
|
if workers is None:
|
|
264
273
|
return dict(_apply_increment_chunk(payload, dt_step, method))
|
|
265
274
|
|
|
266
|
-
|
|
275
|
+
approx_chunk = math.ceil(len(nodes) / (workers * 4)) if workers > 0 else None
|
|
276
|
+
chunk_size = resolve_chunk_size(
|
|
277
|
+
approx_chunk,
|
|
278
|
+
len(nodes),
|
|
279
|
+
minimum=1,
|
|
280
|
+
)
|
|
267
281
|
mp_ctx = get_context("spawn")
|
|
268
282
|
|
|
269
283
|
results: NodalUpdate = {}
|
|
@@ -398,9 +412,7 @@ def _build_gamma_increments(
|
|
|
398
412
|
g4_map = _evaluate_gamma_map(G, nodes, t_end, n_jobs=n_jobs)
|
|
399
413
|
gamma_maps = (g1_map, g_mid_map, g_mid_map, g4_map)
|
|
400
414
|
else: # method == "euler"
|
|
401
|
-
gamma_maps = (
|
|
402
|
-
_evaluate_gamma_map(G, nodes, t_local, n_jobs=n_jobs),
|
|
403
|
-
)
|
|
415
|
+
gamma_maps = (_evaluate_gamma_map(G, nodes, t_local, n_jobs=n_jobs),)
|
|
404
416
|
|
|
405
417
|
return _collect_nodal_increments(G, gamma_maps, method=method)
|
|
406
418
|
|
|
@@ -481,6 +493,8 @@ class DefaultIntegrator(AbstractIntegrator):
|
|
|
481
493
|
method: str | None,
|
|
482
494
|
n_jobs: int | None,
|
|
483
495
|
) -> None:
|
|
496
|
+
"""Integrate the nodal equation updating EPI, ΔEPI and Δ²EPI."""
|
|
497
|
+
|
|
484
498
|
if not isinstance(
|
|
485
499
|
graph, (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph)
|
|
486
500
|
):
|
tnfr/dynamics/integrators.pyi
CHANGED