tnfr 4.5.2__py3-none-any.whl → 8.5.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 +334 -50
- 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 +214 -37
- tnfr/alias.pyi +108 -0
- tnfr/backends/__init__.py +354 -0
- tnfr/backends/jax_backend.py +173 -0
- tnfr/backends/numpy_backend.py +238 -0
- tnfr/backends/optimized_numpy.py +420 -0
- tnfr/backends/torch_backend.py +408 -0
- tnfr/cache.py +149 -556
- tnfr/cache.pyi +13 -0
- tnfr/cli/__init__.py +51 -16
- tnfr/cli/__init__.pyi +26 -0
- tnfr/cli/arguments.py +344 -32
- tnfr/cli/arguments.pyi +29 -0
- tnfr/cli/execution.py +676 -50
- tnfr/cli/execution.pyi +70 -0
- tnfr/cli/interactive_validator.py +614 -0
- tnfr/cli/utils.py +18 -3
- tnfr/cli/utils.pyi +7 -0
- tnfr/cli/validate.py +236 -0
- tnfr/compat/__init__.py +85 -0
- tnfr/compat/dataclass.py +136 -0
- tnfr/compat/jsonschema_stub.py +61 -0
- tnfr/compat/matplotlib_stub.py +73 -0
- tnfr/compat/numpy_stub.py +155 -0
- tnfr/config/__init__.py +224 -0
- tnfr/config/__init__.pyi +10 -0
- tnfr/{constants_glyphs.py → config/constants.py} +26 -20
- tnfr/config/constants.pyi +12 -0
- tnfr/config/defaults.py +54 -0
- tnfr/{constants/core.py → config/defaults_core.py} +59 -6
- tnfr/config/defaults_init.py +33 -0
- tnfr/config/defaults_metric.py +104 -0
- tnfr/config/feature_flags.py +81 -0
- tnfr/config/feature_flags.pyi +16 -0
- tnfr/config/glyph_constants.py +31 -0
- tnfr/config/init.py +77 -0
- tnfr/config/init.pyi +8 -0
- tnfr/config/operator_names.py +254 -0
- tnfr/config/operator_names.pyi +36 -0
- tnfr/config/physics_derivation.py +354 -0
- tnfr/config/presets.py +83 -0
- tnfr/config/presets.pyi +7 -0
- tnfr/config/security.py +927 -0
- tnfr/config/thresholds.py +114 -0
- tnfr/config/tnfr_config.py +498 -0
- tnfr/constants/__init__.py +51 -133
- tnfr/constants/__init__.pyi +92 -0
- tnfr/constants/aliases.py +33 -0
- tnfr/constants/aliases.pyi +27 -0
- tnfr/constants/init.py +3 -1
- tnfr/constants/init.pyi +12 -0
- tnfr/constants/metric.py +9 -15
- tnfr/constants/metric.pyi +19 -0
- tnfr/core/__init__.py +33 -0
- tnfr/core/container.py +226 -0
- tnfr/core/default_implementations.py +329 -0
- tnfr/core/interfaces.py +279 -0
- tnfr/dynamics/__init__.py +213 -633
- tnfr/dynamics/__init__.pyi +83 -0
- tnfr/dynamics/adaptation.py +267 -0
- tnfr/dynamics/adaptation.pyi +7 -0
- tnfr/dynamics/adaptive_sequences.py +189 -0
- tnfr/dynamics/adaptive_sequences.pyi +14 -0
- tnfr/dynamics/aliases.py +23 -0
- tnfr/dynamics/aliases.pyi +19 -0
- tnfr/dynamics/bifurcation.py +232 -0
- tnfr/dynamics/canonical.py +229 -0
- tnfr/dynamics/canonical.pyi +48 -0
- tnfr/dynamics/coordination.py +385 -0
- tnfr/dynamics/coordination.pyi +25 -0
- tnfr/dynamics/dnfr.py +2699 -398
- tnfr/dynamics/dnfr.pyi +26 -0
- tnfr/dynamics/dynamic_limits.py +225 -0
- tnfr/dynamics/feedback.py +252 -0
- tnfr/dynamics/feedback.pyi +24 -0
- tnfr/dynamics/fused_dnfr.py +454 -0
- tnfr/dynamics/homeostasis.py +157 -0
- tnfr/dynamics/homeostasis.pyi +14 -0
- tnfr/dynamics/integrators.py +496 -102
- tnfr/dynamics/integrators.pyi +36 -0
- tnfr/dynamics/learning.py +310 -0
- tnfr/dynamics/learning.pyi +33 -0
- tnfr/dynamics/metabolism.py +254 -0
- tnfr/dynamics/nbody.py +796 -0
- tnfr/dynamics/nbody_tnfr.py +783 -0
- tnfr/dynamics/propagation.py +326 -0
- tnfr/dynamics/runtime.py +908 -0
- tnfr/dynamics/runtime.pyi +77 -0
- tnfr/dynamics/sampling.py +10 -5
- tnfr/dynamics/sampling.pyi +7 -0
- tnfr/dynamics/selectors.py +711 -0
- tnfr/dynamics/selectors.pyi +85 -0
- tnfr/dynamics/structural_clip.py +207 -0
- tnfr/errors/__init__.py +37 -0
- tnfr/errors/contextual.py +492 -0
- tnfr/execution.py +77 -55
- tnfr/execution.pyi +45 -0
- tnfr/extensions/__init__.py +205 -0
- tnfr/extensions/__init__.pyi +18 -0
- tnfr/extensions/base.py +173 -0
- tnfr/extensions/base.pyi +35 -0
- tnfr/extensions/business/__init__.py +71 -0
- tnfr/extensions/business/__init__.pyi +11 -0
- tnfr/extensions/business/cookbook.py +88 -0
- tnfr/extensions/business/cookbook.pyi +8 -0
- tnfr/extensions/business/health_analyzers.py +202 -0
- tnfr/extensions/business/health_analyzers.pyi +9 -0
- tnfr/extensions/business/patterns.py +183 -0
- tnfr/extensions/business/patterns.pyi +8 -0
- tnfr/extensions/medical/__init__.py +73 -0
- tnfr/extensions/medical/__init__.pyi +11 -0
- tnfr/extensions/medical/cookbook.py +88 -0
- tnfr/extensions/medical/cookbook.pyi +8 -0
- tnfr/extensions/medical/health_analyzers.py +181 -0
- tnfr/extensions/medical/health_analyzers.pyi +9 -0
- tnfr/extensions/medical/patterns.py +163 -0
- tnfr/extensions/medical/patterns.pyi +8 -0
- tnfr/flatten.py +29 -50
- tnfr/flatten.pyi +21 -0
- tnfr/gamma.py +66 -53
- tnfr/gamma.pyi +36 -0
- tnfr/glyph_history.py +144 -57
- tnfr/glyph_history.pyi +35 -0
- tnfr/glyph_runtime.py +19 -0
- tnfr/glyph_runtime.pyi +8 -0
- tnfr/immutable.py +70 -30
- tnfr/immutable.pyi +36 -0
- tnfr/initialization.py +22 -16
- tnfr/initialization.pyi +65 -0
- tnfr/io.py +5 -241
- tnfr/io.pyi +13 -0
- tnfr/locking.pyi +7 -0
- tnfr/mathematics/__init__.py +79 -0
- tnfr/mathematics/backend.py +453 -0
- tnfr/mathematics/backend.pyi +99 -0
- tnfr/mathematics/dynamics.py +408 -0
- tnfr/mathematics/dynamics.pyi +90 -0
- tnfr/mathematics/epi.py +391 -0
- tnfr/mathematics/epi.pyi +65 -0
- tnfr/mathematics/generators.py +242 -0
- tnfr/mathematics/generators.pyi +29 -0
- tnfr/mathematics/metrics.py +119 -0
- tnfr/mathematics/metrics.pyi +16 -0
- tnfr/mathematics/operators.py +239 -0
- tnfr/mathematics/operators.pyi +59 -0
- tnfr/mathematics/operators_factory.py +124 -0
- tnfr/mathematics/operators_factory.pyi +11 -0
- tnfr/mathematics/projection.py +87 -0
- tnfr/mathematics/projection.pyi +33 -0
- tnfr/mathematics/runtime.py +182 -0
- tnfr/mathematics/runtime.pyi +64 -0
- tnfr/mathematics/spaces.py +256 -0
- tnfr/mathematics/spaces.pyi +83 -0
- tnfr/mathematics/transforms.py +305 -0
- tnfr/mathematics/transforms.pyi +62 -0
- tnfr/metrics/__init__.py +47 -9
- tnfr/metrics/__init__.pyi +20 -0
- tnfr/metrics/buffer_cache.py +163 -0
- tnfr/metrics/buffer_cache.pyi +24 -0
- tnfr/metrics/cache_utils.py +214 -0
- tnfr/metrics/coherence.py +1510 -330
- tnfr/metrics/coherence.pyi +129 -0
- tnfr/metrics/common.py +23 -16
- tnfr/metrics/common.pyi +35 -0
- tnfr/metrics/core.py +251 -36
- tnfr/metrics/core.pyi +13 -0
- tnfr/metrics/diagnosis.py +709 -110
- tnfr/metrics/diagnosis.pyi +86 -0
- tnfr/metrics/emergence.py +245 -0
- tnfr/metrics/export.py +60 -18
- tnfr/metrics/export.pyi +7 -0
- tnfr/metrics/glyph_timing.py +233 -43
- tnfr/metrics/glyph_timing.pyi +81 -0
- tnfr/metrics/learning_metrics.py +280 -0
- tnfr/metrics/learning_metrics.pyi +21 -0
- tnfr/metrics/phase_coherence.py +351 -0
- tnfr/metrics/phase_compatibility.py +349 -0
- tnfr/metrics/reporting.py +63 -28
- tnfr/metrics/reporting.pyi +25 -0
- tnfr/metrics/sense_index.py +1126 -43
- tnfr/metrics/sense_index.pyi +9 -0
- tnfr/metrics/trig.py +215 -23
- tnfr/metrics/trig.pyi +13 -0
- tnfr/metrics/trig_cache.py +148 -24
- tnfr/metrics/trig_cache.pyi +10 -0
- tnfr/multiscale/__init__.py +32 -0
- tnfr/multiscale/hierarchical.py +517 -0
- tnfr/node.py +646 -140
- tnfr/node.pyi +139 -0
- tnfr/observers.py +160 -45
- tnfr/observers.pyi +31 -0
- tnfr/ontosim.py +23 -19
- tnfr/ontosim.pyi +28 -0
- tnfr/operators/__init__.py +1358 -106
- tnfr/operators/__init__.pyi +31 -0
- tnfr/operators/algebra.py +277 -0
- tnfr/operators/canonical_patterns.py +420 -0
- tnfr/operators/cascade.py +267 -0
- tnfr/operators/cycle_detection.py +358 -0
- tnfr/operators/definitions.py +4108 -0
- tnfr/operators/definitions.pyi +78 -0
- tnfr/operators/grammar.py +1164 -0
- tnfr/operators/grammar.pyi +140 -0
- tnfr/operators/hamiltonian.py +710 -0
- tnfr/operators/health_analyzer.py +809 -0
- tnfr/operators/jitter.py +107 -38
- tnfr/operators/jitter.pyi +11 -0
- tnfr/operators/lifecycle.py +314 -0
- tnfr/operators/metabolism.py +618 -0
- tnfr/operators/metrics.py +2138 -0
- tnfr/operators/network_analysis/__init__.py +27 -0
- tnfr/operators/network_analysis/source_detection.py +186 -0
- tnfr/operators/nodal_equation.py +395 -0
- tnfr/operators/pattern_detection.py +660 -0
- tnfr/operators/patterns.py +669 -0
- tnfr/operators/postconditions/__init__.py +38 -0
- tnfr/operators/postconditions/mutation.py +236 -0
- tnfr/operators/preconditions/__init__.py +1226 -0
- tnfr/operators/preconditions/coherence.py +305 -0
- tnfr/operators/preconditions/dissonance.py +236 -0
- tnfr/operators/preconditions/emission.py +128 -0
- tnfr/operators/preconditions/mutation.py +580 -0
- tnfr/operators/preconditions/reception.py +125 -0
- tnfr/operators/preconditions/resonance.py +364 -0
- tnfr/operators/registry.py +74 -0
- tnfr/operators/registry.pyi +9 -0
- tnfr/operators/remesh.py +1415 -91
- tnfr/operators/remesh.pyi +26 -0
- tnfr/operators/structural_units.py +268 -0
- tnfr/operators/unified_grammar.py +105 -0
- tnfr/parallel/__init__.py +54 -0
- tnfr/parallel/auto_scaler.py +234 -0
- tnfr/parallel/distributed.py +384 -0
- tnfr/parallel/engine.py +238 -0
- tnfr/parallel/gpu_engine.py +420 -0
- tnfr/parallel/monitoring.py +248 -0
- tnfr/parallel/partitioner.py +459 -0
- tnfr/py.typed +0 -0
- tnfr/recipes/__init__.py +22 -0
- tnfr/recipes/cookbook.py +743 -0
- tnfr/rng.py +75 -151
- tnfr/rng.pyi +26 -0
- tnfr/schemas/__init__.py +8 -0
- tnfr/schemas/grammar.json +94 -0
- tnfr/sdk/__init__.py +107 -0
- tnfr/sdk/__init__.pyi +19 -0
- tnfr/sdk/adaptive_system.py +173 -0
- tnfr/sdk/adaptive_system.pyi +21 -0
- tnfr/sdk/builders.py +370 -0
- tnfr/sdk/builders.pyi +51 -0
- tnfr/sdk/fluent.py +1121 -0
- tnfr/sdk/fluent.pyi +74 -0
- tnfr/sdk/templates.py +342 -0
- tnfr/sdk/templates.pyi +41 -0
- tnfr/sdk/utils.py +341 -0
- tnfr/secure_config.py +46 -0
- tnfr/security/__init__.py +70 -0
- tnfr/security/database.py +514 -0
- tnfr/security/subprocess.py +503 -0
- tnfr/security/validation.py +290 -0
- tnfr/selector.py +59 -22
- tnfr/selector.pyi +19 -0
- tnfr/sense.py +92 -67
- tnfr/sense.pyi +23 -0
- tnfr/services/__init__.py +17 -0
- tnfr/services/orchestrator.py +325 -0
- tnfr/sparse/__init__.py +39 -0
- tnfr/sparse/representations.py +492 -0
- tnfr/structural.py +639 -263
- tnfr/structural.pyi +83 -0
- tnfr/telemetry/__init__.py +35 -0
- tnfr/telemetry/cache_metrics.py +226 -0
- tnfr/telemetry/cache_metrics.pyi +64 -0
- tnfr/telemetry/nu_f.py +422 -0
- tnfr/telemetry/nu_f.pyi +108 -0
- tnfr/telemetry/verbosity.py +36 -0
- tnfr/telemetry/verbosity.pyi +15 -0
- tnfr/tokens.py +2 -4
- tnfr/tokens.pyi +36 -0
- tnfr/tools/__init__.py +20 -0
- tnfr/tools/domain_templates.py +478 -0
- tnfr/tools/sequence_generator.py +846 -0
- tnfr/topology/__init__.py +13 -0
- tnfr/topology/asymmetry.py +151 -0
- tnfr/trace.py +300 -126
- tnfr/trace.pyi +42 -0
- tnfr/tutorials/__init__.py +38 -0
- tnfr/tutorials/autonomous_evolution.py +285 -0
- tnfr/tutorials/interactive.py +1576 -0
- tnfr/tutorials/structural_metabolism.py +238 -0
- tnfr/types.py +743 -12
- tnfr/types.pyi +357 -0
- tnfr/units.py +68 -0
- tnfr/units.pyi +13 -0
- tnfr/utils/__init__.py +282 -0
- tnfr/utils/__init__.pyi +215 -0
- tnfr/utils/cache.py +4223 -0
- tnfr/utils/cache.pyi +470 -0
- tnfr/{callback_utils.py → utils/callbacks.py} +26 -39
- tnfr/utils/callbacks.pyi +49 -0
- tnfr/utils/chunks.py +108 -0
- tnfr/utils/chunks.pyi +22 -0
- tnfr/utils/data.py +428 -0
- tnfr/utils/data.pyi +74 -0
- tnfr/utils/graph.py +85 -0
- tnfr/utils/graph.pyi +10 -0
- tnfr/utils/init.py +821 -0
- tnfr/utils/init.pyi +80 -0
- tnfr/utils/io.py +559 -0
- tnfr/utils/io.pyi +66 -0
- tnfr/{helpers → utils}/numeric.py +51 -24
- tnfr/utils/numeric.pyi +21 -0
- tnfr/validation/__init__.py +257 -0
- tnfr/validation/__init__.pyi +85 -0
- tnfr/validation/compatibility.py +460 -0
- tnfr/validation/compatibility.pyi +6 -0
- tnfr/validation/config.py +73 -0
- tnfr/validation/graph.py +139 -0
- tnfr/validation/graph.pyi +18 -0
- tnfr/validation/input_validation.py +755 -0
- tnfr/validation/invariants.py +712 -0
- tnfr/validation/rules.py +253 -0
- tnfr/validation/rules.pyi +44 -0
- tnfr/validation/runtime.py +279 -0
- tnfr/validation/runtime.pyi +28 -0
- tnfr/validation/sequence_validator.py +162 -0
- tnfr/validation/soft_filters.py +170 -0
- tnfr/validation/soft_filters.pyi +32 -0
- tnfr/validation/spectral.py +164 -0
- tnfr/validation/spectral.pyi +42 -0
- tnfr/validation/validator.py +1266 -0
- tnfr/validation/window.py +39 -0
- tnfr/validation/window.pyi +1 -0
- tnfr/visualization/__init__.py +98 -0
- tnfr/visualization/cascade_viz.py +256 -0
- tnfr/visualization/hierarchy.py +284 -0
- tnfr/visualization/sequence_plotter.py +784 -0
- tnfr/viz/__init__.py +60 -0
- tnfr/viz/matplotlib.py +278 -0
- tnfr/viz/matplotlib.pyi +35 -0
- tnfr-8.5.0.dist-info/METADATA +573 -0
- tnfr-8.5.0.dist-info/RECORD +353 -0
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/entry_points.txt +1 -0
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/licenses/LICENSE.md +1 -1
- tnfr/collections_utils.py +0 -300
- tnfr/config.py +0 -32
- 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-8.5.0.dist-info}/WHEEL +0 -0
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
tnfr/dynamics/dnfr.pyi
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from tnfr.types import DeltaNFRHook, TNFRGraph
|
|
6
|
+
from tnfr.utils.cache import DnfrCache as DnfrCache
|
|
7
|
+
|
|
8
|
+
__all__: tuple[str, ...]
|
|
9
|
+
|
|
10
|
+
def default_compute_delta_nfr(
|
|
11
|
+
G: TNFRGraph,
|
|
12
|
+
*,
|
|
13
|
+
cache_size: int | None = ...,
|
|
14
|
+
n_jobs: int | None = ...,
|
|
15
|
+
) -> None: ...
|
|
16
|
+
def dnfr_epi_vf_mixed(G: TNFRGraph, *, n_jobs: int | None = ...) -> None: ...
|
|
17
|
+
def dnfr_laplacian(G: TNFRGraph, *, n_jobs: int | None = ...) -> None: ...
|
|
18
|
+
def dnfr_phase_only(G: TNFRGraph, *, n_jobs: int | None = ...) -> None: ...
|
|
19
|
+
def set_delta_nfr_hook(
|
|
20
|
+
G: TNFRGraph,
|
|
21
|
+
func: DeltaNFRHook,
|
|
22
|
+
*,
|
|
23
|
+
name: str | None = ...,
|
|
24
|
+
note: str | None = ...,
|
|
25
|
+
) -> None: ...
|
|
26
|
+
def __getattr__(name: str) -> Any: ...
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"""Dynamic canonical limits based on network coherence.
|
|
2
|
+
|
|
3
|
+
This module implements dynamic canonical limits for EPI and νf that adapt
|
|
4
|
+
based on network coherence metrics. This addresses the theoretical question
|
|
5
|
+
of whether fixed limits contradict TNFR's self-organizing principles.
|
|
6
|
+
|
|
7
|
+
Theoretical Foundation
|
|
8
|
+
----------------------
|
|
9
|
+
TNFR paradigm principles:
|
|
10
|
+
1. **Operational fractality**: Patterns should scale without artificial bounds
|
|
11
|
+
2. **Self-organization**: System should find its own natural limits
|
|
12
|
+
3. **Coherence emergence**: Stability arises from resonance, not external constraints
|
|
13
|
+
|
|
14
|
+
Fixed limits may contradict these principles by imposing external constraints
|
|
15
|
+
that don't emerge from the system's own dynamics. Dynamic limits address this
|
|
16
|
+
by making bounds proportional to network coherence metrics.
|
|
17
|
+
|
|
18
|
+
Dynamic Limit Formulas
|
|
19
|
+
----------------------
|
|
20
|
+
EPI effective maximum:
|
|
21
|
+
EPI_effective_max(t) = EPI_base_max × (1 + α × C(t) × Si_avg)
|
|
22
|
+
|
|
23
|
+
νf effective maximum:
|
|
24
|
+
νf_effective_max(t) = νf_base_max × (1 + β × R_kuramoto)
|
|
25
|
+
|
|
26
|
+
Where:
|
|
27
|
+
- C(t): Global coherence at time t (0 to 1)
|
|
28
|
+
- Si_avg: Average sense index across network (0 to 1+)
|
|
29
|
+
- R_kuramoto: Kuramoto order parameter (0 to 1)
|
|
30
|
+
- α, β: Expansion coefficients (default: 0.5, 0.3)
|
|
31
|
+
|
|
32
|
+
Theoretical Justification
|
|
33
|
+
--------------------------
|
|
34
|
+
1. **Coherent networks** (high C(t), Si) can sustain higher EPI values
|
|
35
|
+
2. **Synchronized networks** (high R_kuramoto) can sustain higher νf
|
|
36
|
+
3. **Self-regulation** through coupling to system state
|
|
37
|
+
4. **Fractality preservation** via proportional scaling
|
|
38
|
+
5. **Safety bounds** via maximum expansion factors
|
|
39
|
+
|
|
40
|
+
References
|
|
41
|
+
----------
|
|
42
|
+
- AGENTS.md: Section 3 (Canonical invariants)
|
|
43
|
+
- Issue fermga/TNFR-Python-Engine#2624: Theoretical review of limits
|
|
44
|
+
- TNFR.pdf: Nodal equation and coherence theory
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
from __future__ import annotations
|
|
48
|
+
|
|
49
|
+
from dataclasses import dataclass
|
|
50
|
+
from typing import TYPE_CHECKING
|
|
51
|
+
|
|
52
|
+
from ..alias import collect_attr
|
|
53
|
+
from ..constants.aliases import ALIAS_SI
|
|
54
|
+
from ..metrics.common import compute_coherence
|
|
55
|
+
from ..observers import kuramoto_order
|
|
56
|
+
from ..utils import get_numpy
|
|
57
|
+
|
|
58
|
+
if TYPE_CHECKING:
|
|
59
|
+
from ..types import TNFRGraph
|
|
60
|
+
|
|
61
|
+
__all__ = (
|
|
62
|
+
"DynamicLimits",
|
|
63
|
+
"DynamicLimitsConfig",
|
|
64
|
+
"compute_dynamic_limits",
|
|
65
|
+
"DEFAULT_SI_FALLBACK",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Default fallback value for sense index when nodes have no Si attribute
|
|
69
|
+
# This represents a "neutral" sense index - neither high stability nor instability
|
|
70
|
+
DEFAULT_SI_FALLBACK = 0.5
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(frozen=True)
|
|
74
|
+
class DynamicLimitsConfig:
|
|
75
|
+
"""Configuration for dynamic canonical limits.
|
|
76
|
+
|
|
77
|
+
Attributes:
|
|
78
|
+
base_epi_max: Base maximum for EPI (static fallback)
|
|
79
|
+
base_vf_max: Base maximum for νf (static fallback)
|
|
80
|
+
alpha: Expansion coefficient for EPI (via C(t) × Si)
|
|
81
|
+
beta: Expansion coefficient for νf (via R_kuramoto)
|
|
82
|
+
max_expansion_factor: Maximum allowed expansion multiplier
|
|
83
|
+
enabled: Whether dynamic limits are active
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
base_epi_max: float = 1.0
|
|
87
|
+
base_vf_max: float = 10.0
|
|
88
|
+
alpha: float = 0.5
|
|
89
|
+
beta: float = 0.3
|
|
90
|
+
max_expansion_factor: float = 3.0
|
|
91
|
+
enabled: bool = True
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass(frozen=True)
|
|
95
|
+
class DynamicLimits:
|
|
96
|
+
"""Result of dynamic limits computation.
|
|
97
|
+
|
|
98
|
+
Attributes:
|
|
99
|
+
epi_max_effective: Computed effective maximum for EPI
|
|
100
|
+
vf_max_effective: Computed effective maximum for νf
|
|
101
|
+
coherence: C(t) value used in computation
|
|
102
|
+
si_avg: Average Si value used in computation
|
|
103
|
+
kuramoto_r: Kuramoto order parameter used in computation
|
|
104
|
+
coherence_factor: Combined coherence metric (C(t) × Si_avg)
|
|
105
|
+
config: Configuration used for computation
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
epi_max_effective: float
|
|
109
|
+
vf_max_effective: float
|
|
110
|
+
coherence: float
|
|
111
|
+
si_avg: float
|
|
112
|
+
kuramoto_r: float
|
|
113
|
+
coherence_factor: float
|
|
114
|
+
config: DynamicLimitsConfig
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def compute_dynamic_limits(
|
|
118
|
+
G: TNFRGraph,
|
|
119
|
+
config: DynamicLimitsConfig | None = None,
|
|
120
|
+
) -> DynamicLimits:
|
|
121
|
+
"""Compute dynamic canonical limits based on network state.
|
|
122
|
+
|
|
123
|
+
This function computes effective maximum values for EPI and νf that
|
|
124
|
+
adapt based on the network's coherence metrics. More coherent networks
|
|
125
|
+
are allowed higher values, reflecting their greater structural stability.
|
|
126
|
+
|
|
127
|
+
The computation respects TNFR invariants:
|
|
128
|
+
- Operator closure: bounds scale but remain finite
|
|
129
|
+
- Structural semantics: expansion proportional to coherence
|
|
130
|
+
- Self-organization: limits emerge from system state
|
|
131
|
+
- Fractality: proportional scaling preserves structure
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
G: TNFR graph with node attributes
|
|
135
|
+
config: Configuration for dynamic limits (uses defaults if None)
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
DynamicLimits containing effective bounds and metrics
|
|
139
|
+
|
|
140
|
+
Examples:
|
|
141
|
+
>>> import networkx as nx
|
|
142
|
+
>>> G = nx.Graph()
|
|
143
|
+
>>> G.add_node(0, **{"νf": 1.0, "theta": 0.0, "EPI": 0.5, "Si": 0.7})
|
|
144
|
+
>>> limits = compute_dynamic_limits(G)
|
|
145
|
+
>>> limits.epi_max_effective >= 1.0 # May be expanded
|
|
146
|
+
True
|
|
147
|
+
|
|
148
|
+
>>> # With custom configuration
|
|
149
|
+
>>> config = DynamicLimitsConfig(alpha=0.8, beta=0.5)
|
|
150
|
+
>>> limits = compute_dynamic_limits(G, config)
|
|
151
|
+
>>> limits.config.alpha
|
|
152
|
+
0.8
|
|
153
|
+
|
|
154
|
+
Notes:
|
|
155
|
+
- Returns base limits if graph is empty
|
|
156
|
+
- Clamps expansion to max_expansion_factor for safety
|
|
157
|
+
- If config.enabled is False, returns base limits only
|
|
158
|
+
- All metrics computed using existing TNFR functions
|
|
159
|
+
"""
|
|
160
|
+
if config is None:
|
|
161
|
+
config = DynamicLimitsConfig()
|
|
162
|
+
|
|
163
|
+
# Handle empty graph
|
|
164
|
+
n_nodes = G.number_of_nodes()
|
|
165
|
+
if n_nodes == 0:
|
|
166
|
+
return DynamicLimits(
|
|
167
|
+
epi_max_effective=config.base_epi_max,
|
|
168
|
+
vf_max_effective=config.base_vf_max,
|
|
169
|
+
coherence=0.0,
|
|
170
|
+
si_avg=0.0,
|
|
171
|
+
kuramoto_r=0.0,
|
|
172
|
+
coherence_factor=0.0,
|
|
173
|
+
config=config,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
# If dynamic limits disabled, return base values
|
|
177
|
+
if not config.enabled:
|
|
178
|
+
return DynamicLimits(
|
|
179
|
+
epi_max_effective=config.base_epi_max,
|
|
180
|
+
vf_max_effective=config.base_vf_max,
|
|
181
|
+
coherence=1.0,
|
|
182
|
+
si_avg=1.0,
|
|
183
|
+
kuramoto_r=1.0,
|
|
184
|
+
coherence_factor=1.0,
|
|
185
|
+
config=config,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Compute coherence metrics
|
|
189
|
+
C_t = compute_coherence(G)
|
|
190
|
+
|
|
191
|
+
# Compute average sense index
|
|
192
|
+
np_module = get_numpy()
|
|
193
|
+
si_values = collect_attr(G, G.nodes, ALIAS_SI, DEFAULT_SI_FALLBACK, np=np_module)
|
|
194
|
+
if np_module is not None:
|
|
195
|
+
Si_avg = float(np_module.mean(si_values))
|
|
196
|
+
else:
|
|
197
|
+
Si_avg = sum(si_values) / len(si_values) if si_values else DEFAULT_SI_FALLBACK
|
|
198
|
+
|
|
199
|
+
# Compute Kuramoto order parameter
|
|
200
|
+
R_kuramoto = kuramoto_order(G)
|
|
201
|
+
|
|
202
|
+
# Compute coherence factor
|
|
203
|
+
coherence_factor = C_t * Si_avg
|
|
204
|
+
|
|
205
|
+
# Compute dynamic limits
|
|
206
|
+
epi_expansion = 1.0 + config.alpha * coherence_factor
|
|
207
|
+
vf_expansion = 1.0 + config.beta * R_kuramoto
|
|
208
|
+
|
|
209
|
+
# Apply maximum expansion factor as safety bound
|
|
210
|
+
epi_expansion = min(epi_expansion, config.max_expansion_factor)
|
|
211
|
+
vf_expansion = min(vf_expansion, config.max_expansion_factor)
|
|
212
|
+
|
|
213
|
+
# Compute effective limits
|
|
214
|
+
epi_max_effective = config.base_epi_max * epi_expansion
|
|
215
|
+
vf_max_effective = config.base_vf_max * vf_expansion
|
|
216
|
+
|
|
217
|
+
return DynamicLimits(
|
|
218
|
+
epi_max_effective=epi_max_effective,
|
|
219
|
+
vf_max_effective=vf_max_effective,
|
|
220
|
+
coherence=C_t,
|
|
221
|
+
si_avg=Si_avg,
|
|
222
|
+
kuramoto_r=R_kuramoto,
|
|
223
|
+
coherence_factor=coherence_factor,
|
|
224
|
+
config=config,
|
|
225
|
+
)
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"""Structural feedback loops for TNFR adaptive dynamics.
|
|
2
|
+
|
|
3
|
+
This module implements feedback loops that automatically adjust nodal parameters
|
|
4
|
+
based on current structural state. Feedback loops enable autonomous regulation
|
|
5
|
+
and homeostatic cycles as specified in TNFR dynamics theory.
|
|
6
|
+
|
|
7
|
+
The core principle: ΔNFR → operator selection → application → measure effect →
|
|
8
|
+
adjust thresholds, creating closed-loop structural regulation.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import TYPE_CHECKING, Any
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from ..types import TNFRGraph, NodeId
|
|
17
|
+
|
|
18
|
+
from ..alias import get_attr
|
|
19
|
+
from ..constants.aliases import ALIAS_DNFR, ALIAS_EPI, ALIAS_VF
|
|
20
|
+
from ..operators.registry import get_operator_class
|
|
21
|
+
from ..config.operator_names import (
|
|
22
|
+
COHERENCE,
|
|
23
|
+
DISSONANCE,
|
|
24
|
+
EMISSION,
|
|
25
|
+
SELF_ORGANIZATION,
|
|
26
|
+
SILENCE,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
__all__ = ["StructuralFeedbackLoop"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class StructuralFeedbackLoop:
|
|
33
|
+
"""Feedback loop that adapts nodal dynamics based on structural state.
|
|
34
|
+
|
|
35
|
+
This class implements closed-loop regulation where the system measures its
|
|
36
|
+
current coherence state and selects appropriate operators to maintain
|
|
37
|
+
target coherence levels. The feedback loop adjusts thresholds adaptively
|
|
38
|
+
based on performance.
|
|
39
|
+
|
|
40
|
+
**Feedback Cycle:**
|
|
41
|
+
|
|
42
|
+
1. **Measure**: Compute current coherence from ΔNFR and local state
|
|
43
|
+
2. **Decide**: Select operator based on deviation from target
|
|
44
|
+
3. **Act**: Apply selected operator
|
|
45
|
+
4. **Learn**: Adjust thresholds based on achieved coherence
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
graph : TNFRGraph
|
|
50
|
+
Graph containing the regulated node
|
|
51
|
+
node : NodeId
|
|
52
|
+
Identifier of the node to regulate
|
|
53
|
+
target_coherence : float, default=0.7
|
|
54
|
+
Target coherence level (C_target)
|
|
55
|
+
tau_adaptive : float, default=0.1
|
|
56
|
+
Initial bifurcation threshold (adaptive)
|
|
57
|
+
learning_rate : float, default=0.05
|
|
58
|
+
Rate of threshold adaptation
|
|
59
|
+
coherence_tolerance_low : float, default=0.2
|
|
60
|
+
Deviation below target that triggers stabilization
|
|
61
|
+
coherence_tolerance_high : float, default=0.1
|
|
62
|
+
Deviation above target that triggers exploration
|
|
63
|
+
dnfr_threshold : float, default=0.15
|
|
64
|
+
ΔNFR threshold for self-organization
|
|
65
|
+
epi_threshold : float, default=0.3
|
|
66
|
+
EPI threshold for emission
|
|
67
|
+
|
|
68
|
+
Attributes
|
|
69
|
+
----------
|
|
70
|
+
G : TNFRGraph
|
|
71
|
+
Graph containing the node
|
|
72
|
+
node : NodeId
|
|
73
|
+
Node identifier
|
|
74
|
+
target_coherence : float
|
|
75
|
+
Target C(t) for homeostasis
|
|
76
|
+
tau_adaptive : float
|
|
77
|
+
Adaptive bifurcation threshold
|
|
78
|
+
learning_rate : float
|
|
79
|
+
Threshold adjustment rate
|
|
80
|
+
COHERENCE_TOL_LOW : float
|
|
81
|
+
Lower tolerance for coherence regulation
|
|
82
|
+
COHERENCE_TOL_HIGH : float
|
|
83
|
+
Upper tolerance for coherence regulation
|
|
84
|
+
DNFR_THRESHOLD : float
|
|
85
|
+
Threshold for self-organization activation
|
|
86
|
+
EPI_THRESHOLD : float
|
|
87
|
+
Threshold for emission activation
|
|
88
|
+
|
|
89
|
+
Examples
|
|
90
|
+
--------
|
|
91
|
+
>>> from tnfr.structural import create_nfr
|
|
92
|
+
>>> from tnfr.dynamics.feedback import StructuralFeedbackLoop
|
|
93
|
+
>>> G, node = create_nfr("test_node")
|
|
94
|
+
>>> loop = StructuralFeedbackLoop(G, node, target_coherence=0.7)
|
|
95
|
+
>>> operator_name = loop.regulate()
|
|
96
|
+
>>> loop.homeostatic_cycle(num_steps=5)
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
# Regulation thresholds
|
|
100
|
+
COHERENCE_TOL_LOW = 0.2 # Deviation below target triggers stabilization
|
|
101
|
+
COHERENCE_TOL_HIGH = 0.1 # Deviation above target triggers exploration
|
|
102
|
+
DNFR_THRESHOLD = 0.15 # ΔNFR threshold for self-organization
|
|
103
|
+
EPI_THRESHOLD = 0.3 # EPI threshold for emission
|
|
104
|
+
|
|
105
|
+
def __init__(
|
|
106
|
+
self,
|
|
107
|
+
graph: TNFRGraph,
|
|
108
|
+
node: NodeId,
|
|
109
|
+
target_coherence: float = 0.7,
|
|
110
|
+
tau_adaptive: float = 0.1,
|
|
111
|
+
learning_rate: float = 0.05,
|
|
112
|
+
coherence_tolerance_low: float = COHERENCE_TOL_LOW,
|
|
113
|
+
coherence_tolerance_high: float = COHERENCE_TOL_HIGH,
|
|
114
|
+
dnfr_threshold: float = DNFR_THRESHOLD,
|
|
115
|
+
epi_threshold: float = EPI_THRESHOLD,
|
|
116
|
+
) -> None:
|
|
117
|
+
self.G = graph
|
|
118
|
+
self.node = node
|
|
119
|
+
self.target_coherence = float(target_coherence)
|
|
120
|
+
self.tau_adaptive = float(tau_adaptive)
|
|
121
|
+
self.learning_rate = float(learning_rate)
|
|
122
|
+
self.COHERENCE_TOL_LOW = float(coherence_tolerance_low)
|
|
123
|
+
self.COHERENCE_TOL_HIGH = float(coherence_tolerance_high)
|
|
124
|
+
self.DNFR_THRESHOLD = float(dnfr_threshold)
|
|
125
|
+
self.EPI_THRESHOLD = float(epi_threshold)
|
|
126
|
+
|
|
127
|
+
def regulate(self) -> str:
|
|
128
|
+
"""Select appropriate operator based on current structural state.
|
|
129
|
+
|
|
130
|
+
Decision logic follows TNFR canonical regulation principles:
|
|
131
|
+
|
|
132
|
+
- **Low coherence**: Stabilize with IL (Coherence)
|
|
133
|
+
- **High coherence**: Explore with OZ (Dissonance)
|
|
134
|
+
- **High ΔNFR**: Self-organize with THOL
|
|
135
|
+
- **Low EPI**: Activate with AL (Emission)
|
|
136
|
+
- **Stable**: Consolidate with SHA (Silence)
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
str
|
|
141
|
+
Operator name to apply
|
|
142
|
+
|
|
143
|
+
Notes
|
|
144
|
+
-----
|
|
145
|
+
The regulation logic implements structural decision-making based on
|
|
146
|
+
current node state. It avoids arbitrary choices by following TNFR
|
|
147
|
+
coherence principles.
|
|
148
|
+
"""
|
|
149
|
+
dnfr = get_attr(self.G.nodes[self.node], ALIAS_DNFR, 0.0)
|
|
150
|
+
epi = get_attr(self.G.nodes[self.node], ALIAS_EPI, 0.0)
|
|
151
|
+
|
|
152
|
+
# Compute local coherence estimate
|
|
153
|
+
coherence = self._compute_local_coherence()
|
|
154
|
+
|
|
155
|
+
# Structural decision tree
|
|
156
|
+
if coherence < self.target_coherence - self.COHERENCE_TOL_LOW:
|
|
157
|
+
# Very low coherence → stabilize
|
|
158
|
+
return COHERENCE
|
|
159
|
+
elif coherence > self.target_coherence + self.COHERENCE_TOL_HIGH:
|
|
160
|
+
# High coherence → explore
|
|
161
|
+
return DISSONANCE
|
|
162
|
+
elif dnfr > self.DNFR_THRESHOLD:
|
|
163
|
+
# High reorganization pressure → self-organize
|
|
164
|
+
return SELF_ORGANIZATION
|
|
165
|
+
elif epi < self.EPI_THRESHOLD:
|
|
166
|
+
# Low activation → emit
|
|
167
|
+
return EMISSION
|
|
168
|
+
else:
|
|
169
|
+
# Stable state → consolidate
|
|
170
|
+
return SILENCE
|
|
171
|
+
|
|
172
|
+
def _compute_local_coherence(self) -> float:
|
|
173
|
+
"""Estimate local coherence from ΔNFR.
|
|
174
|
+
|
|
175
|
+
Coherence is inversely proportional to reorganization pressure.
|
|
176
|
+
When ΔNFR is low, coherence is high (structure is stable).
|
|
177
|
+
|
|
178
|
+
Returns
|
|
179
|
+
-------
|
|
180
|
+
float
|
|
181
|
+
Estimated coherence in [0, 1]
|
|
182
|
+
"""
|
|
183
|
+
dnfr = get_attr(self.G.nodes[self.node], ALIAS_DNFR, 0.0)
|
|
184
|
+
# Coherence inversely proportional to |ΔNFR|
|
|
185
|
+
return max(0.0, min(1.0, 1.0 - abs(dnfr)))
|
|
186
|
+
|
|
187
|
+
def adapt_thresholds(self, performance_metric: float) -> None:
|
|
188
|
+
"""Adapt thresholds based on achieved performance.
|
|
189
|
+
|
|
190
|
+
Uses proportional feedback control to adjust tau_adaptive toward
|
|
191
|
+
target coherence. This implements learning in the feedback loop.
|
|
192
|
+
|
|
193
|
+
Parameters
|
|
194
|
+
----------
|
|
195
|
+
performance_metric : float
|
|
196
|
+
Achieved coherence or other performance measure
|
|
197
|
+
|
|
198
|
+
Notes
|
|
199
|
+
-----
|
|
200
|
+
Threshold adaptation follows:
|
|
201
|
+
|
|
202
|
+
.. math::
|
|
203
|
+
|
|
204
|
+
\\tau_{t+1} = \\tau_t + \\alpha (C_{target} - C_{achieved})
|
|
205
|
+
|
|
206
|
+
where α is the learning rate.
|
|
207
|
+
"""
|
|
208
|
+
error = self.target_coherence - performance_metric
|
|
209
|
+
|
|
210
|
+
# Proportional adjustment
|
|
211
|
+
self.tau_adaptive += self.learning_rate * error
|
|
212
|
+
|
|
213
|
+
# Clamp to valid range
|
|
214
|
+
self.tau_adaptive = max(0.05, min(0.25, self.tau_adaptive))
|
|
215
|
+
|
|
216
|
+
def homeostatic_cycle(self, num_steps: int = 10) -> None:
|
|
217
|
+
"""Execute homeostatic regulation cycle.
|
|
218
|
+
|
|
219
|
+
Maintains target coherence through repeated sense-decide-act-learn cycles.
|
|
220
|
+
|
|
221
|
+
Parameters
|
|
222
|
+
----------
|
|
223
|
+
num_steps : int, default=10
|
|
224
|
+
Number of regulation steps
|
|
225
|
+
|
|
226
|
+
Notes
|
|
227
|
+
-----
|
|
228
|
+
Each step:
|
|
229
|
+
|
|
230
|
+
1. Measures current coherence
|
|
231
|
+
2. Selects operator via regulate()
|
|
232
|
+
3. Applies operator
|
|
233
|
+
4. Measures new coherence
|
|
234
|
+
5. Adapts thresholds
|
|
235
|
+
|
|
236
|
+
This implements autonomous structural homeostasis.
|
|
237
|
+
"""
|
|
238
|
+
for step in range(num_steps):
|
|
239
|
+
# Measure state before
|
|
240
|
+
coherence_before = self._compute_local_coherence()
|
|
241
|
+
|
|
242
|
+
# Select and apply operator
|
|
243
|
+
operator_name = self.regulate()
|
|
244
|
+
operator_class = get_operator_class(operator_name)
|
|
245
|
+
operator = operator_class()
|
|
246
|
+
operator(self.G, self.node, tau=self.tau_adaptive)
|
|
247
|
+
|
|
248
|
+
# Measure state after
|
|
249
|
+
coherence_after = self._compute_local_coherence()
|
|
250
|
+
|
|
251
|
+
# Adapt thresholds based on performance
|
|
252
|
+
self.adapt_thresholds(coherence_after)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Type stubs for tnfr.dynamics.feedback module."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
from ..types import TNFRGraph, NodeId
|
|
5
|
+
|
|
6
|
+
class StructuralFeedbackLoop:
|
|
7
|
+
G: TNFRGraph
|
|
8
|
+
node: NodeId
|
|
9
|
+
target_coherence: float
|
|
10
|
+
tau_adaptive: float
|
|
11
|
+
learning_rate: float
|
|
12
|
+
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
graph: TNFRGraph,
|
|
16
|
+
node: NodeId,
|
|
17
|
+
target_coherence: float = ...,
|
|
18
|
+
tau_adaptive: float = ...,
|
|
19
|
+
learning_rate: float = ...,
|
|
20
|
+
) -> None: ...
|
|
21
|
+
def regulate(self) -> str: ...
|
|
22
|
+
def _compute_local_coherence(self) -> float: ...
|
|
23
|
+
def adapt_thresholds(self, performance_metric: float) -> None: ...
|
|
24
|
+
def homeostatic_cycle(self, num_steps: int = ...) -> None: ...
|