tnfr 3.0.3__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 +375 -56
- 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 +723 -0
- 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 +171 -0
- tnfr/cache.pyi +13 -0
- tnfr/cli/__init__.py +110 -0
- tnfr/cli/__init__.pyi +26 -0
- tnfr/cli/arguments.py +489 -0
- tnfr/cli/arguments.pyi +29 -0
- tnfr/cli/execution.py +914 -0
- tnfr/cli/execution.pyi +70 -0
- tnfr/cli/interactive_validator.py +614 -0
- tnfr/cli/utils.py +51 -0
- 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/config/constants.py +104 -0
- tnfr/config/constants.pyi +12 -0
- tnfr/config/defaults.py +54 -0
- tnfr/config/defaults_core.py +212 -0
- 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 +92 -0
- tnfr/constants/__init__.pyi +92 -0
- tnfr/constants/aliases.py +33 -0
- tnfr/constants/aliases.pyi +27 -0
- tnfr/constants/init.py +33 -0
- tnfr/constants/init.pyi +12 -0
- tnfr/constants/metric.py +104 -0
- 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 +238 -0
- 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 +3034 -0
- 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 +661 -0
- 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 +36 -0
- 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 +223 -0
- 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 +262 -0
- tnfr/flatten.pyi +21 -0
- tnfr/gamma.py +354 -0
- tnfr/gamma.pyi +36 -0
- tnfr/glyph_history.py +377 -0
- tnfr/glyph_history.pyi +35 -0
- tnfr/glyph_runtime.py +19 -0
- tnfr/glyph_runtime.pyi +8 -0
- tnfr/immutable.py +218 -0
- tnfr/immutable.pyi +36 -0
- tnfr/initialization.py +203 -0
- tnfr/initialization.pyi +65 -0
- tnfr/io.py +10 -0
- tnfr/io.pyi +13 -0
- tnfr/locking.py +37 -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 +79 -0
- 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 +2009 -0
- tnfr/metrics/coherence.pyi +129 -0
- tnfr/metrics/common.py +158 -0
- tnfr/metrics/common.pyi +35 -0
- tnfr/metrics/core.py +316 -0
- tnfr/metrics/core.pyi +13 -0
- tnfr/metrics/diagnosis.py +833 -0
- tnfr/metrics/diagnosis.pyi +86 -0
- tnfr/metrics/emergence.py +245 -0
- tnfr/metrics/export.py +179 -0
- tnfr/metrics/export.pyi +7 -0
- tnfr/metrics/glyph_timing.py +379 -0
- 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 +183 -0
- tnfr/metrics/reporting.pyi +25 -0
- tnfr/metrics/sense_index.py +1203 -0
- tnfr/metrics/sense_index.pyi +9 -0
- tnfr/metrics/trig.py +373 -0
- tnfr/metrics/trig.pyi +13 -0
- tnfr/metrics/trig_cache.py +233 -0
- tnfr/metrics/trig_cache.pyi +10 -0
- tnfr/multiscale/__init__.py +32 -0
- tnfr/multiscale/hierarchical.py +517 -0
- tnfr/node.py +763 -0
- tnfr/node.pyi +139 -0
- tnfr/observers.py +255 -130
- tnfr/observers.pyi +31 -0
- tnfr/ontosim.py +144 -137
- tnfr/ontosim.pyi +28 -0
- tnfr/operators/__init__.py +1672 -0
- 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 +272 -0
- 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 +1809 -0
- 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 +178 -0
- 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 +247 -0
- tnfr/selector.pyi +19 -0
- tnfr/sense.py +378 -0
- 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 +705 -0
- 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 +58 -0
- 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 +543 -0
- 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 +775 -0
- 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/utils/callbacks.py +375 -0
- 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/utils/numeric.py +114 -0
- 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-8.5.0.dist-info/entry_points.txt +3 -0
- tnfr-3.0.3.dist-info/licenses/LICENSE.txt → tnfr-8.5.0.dist-info/licenses/LICENSE.md +1 -1
- tnfr/constants.py +0 -183
- tnfr/dynamics.py +0 -543
- tnfr/helpers.py +0 -198
- tnfr/main.py +0 -37
- tnfr/operators.py +0 -296
- tnfr-3.0.3.dist-info/METADATA +0 -35
- tnfr-3.0.3.dist-info/RECORD +0 -13
- {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
- {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""Adaptive sequence selection for TNFR operator trajectories.
|
|
2
|
+
|
|
3
|
+
This module implements learning-based selection of operator sequences.
|
|
4
|
+
Rather than executing fixed sequences, the system learns which sequences
|
|
5
|
+
work best for given contexts and adapts its selection over time.
|
|
6
|
+
|
|
7
|
+
The approach combines predefined canonical sequences with epsilon-greedy
|
|
8
|
+
exploration to balance exploitation (use known good sequences) with
|
|
9
|
+
exploration (try new patterns).
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import random
|
|
15
|
+
from typing import TYPE_CHECKING, Any, Dict, List
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from ..types import TNFRGraph, NodeId
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
import numpy as np
|
|
22
|
+
except ImportError:
|
|
23
|
+
np = None # type: ignore[assignment]
|
|
24
|
+
|
|
25
|
+
from ..config.operator_names import (
|
|
26
|
+
COHERENCE,
|
|
27
|
+
DISSONANCE,
|
|
28
|
+
EMISSION,
|
|
29
|
+
MUTATION,
|
|
30
|
+
RECEPTION,
|
|
31
|
+
RECURSIVITY,
|
|
32
|
+
RESONANCE,
|
|
33
|
+
SELF_ORGANIZATION,
|
|
34
|
+
SILENCE,
|
|
35
|
+
TRANSITION,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
__all__ = ["AdaptiveSequenceSelector"]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AdaptiveSequenceSelector:
|
|
42
|
+
"""Learns and selects optimal operator sequences based on context.
|
|
43
|
+
|
|
44
|
+
This class maintains a pool of canonical operator sequences and tracks
|
|
45
|
+
their performance over time. It uses epsilon-greedy selection to balance
|
|
46
|
+
exploitation of known-good sequences with exploration of alternatives.
|
|
47
|
+
|
|
48
|
+
**Selection Strategy:**
|
|
49
|
+
|
|
50
|
+
- **Exploitation (80%)**: Choose sequence with best historical performance
|
|
51
|
+
- **Exploration (20%)**: Random selection to discover new patterns
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
graph : TNFRGraph
|
|
56
|
+
Graph containing the node
|
|
57
|
+
node : NodeId
|
|
58
|
+
Identifier of the node
|
|
59
|
+
|
|
60
|
+
Attributes
|
|
61
|
+
----------
|
|
62
|
+
G : TNFRGraph
|
|
63
|
+
Graph reference
|
|
64
|
+
node : NodeId
|
|
65
|
+
Node identifier
|
|
66
|
+
sequences : dict[str, list[str]]
|
|
67
|
+
Pool of canonical operator sequences
|
|
68
|
+
performance : dict[str, list[float]]
|
|
69
|
+
Historical performance for each sequence
|
|
70
|
+
|
|
71
|
+
Examples
|
|
72
|
+
--------
|
|
73
|
+
>>> from tnfr.structural import create_nfr
|
|
74
|
+
>>> from tnfr.dynamics.adaptive_sequences import AdaptiveSequenceSelector
|
|
75
|
+
>>> G, node = create_nfr("test_node")
|
|
76
|
+
>>> selector = AdaptiveSequenceSelector(G, node)
|
|
77
|
+
>>> context = {"goal": "stability", "urgency": 0.5}
|
|
78
|
+
>>> sequence = selector.select_sequence(context)
|
|
79
|
+
>>> selector.record_performance("basic_activation", 0.85)
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
def __init__(self, graph: TNFRGraph, node: NodeId) -> None:
|
|
83
|
+
self.G = graph
|
|
84
|
+
self.node = node
|
|
85
|
+
|
|
86
|
+
# Canonical operator sequences
|
|
87
|
+
# Note: Sequences are designed to comply with TNFR grammar rules
|
|
88
|
+
self.sequences: Dict[str, List[str]] = {
|
|
89
|
+
"basic_activation": [EMISSION, COHERENCE],
|
|
90
|
+
"deep_learning": [EMISSION, RECEPTION, COHERENCE],
|
|
91
|
+
"exploration": [EMISSION, DISSONANCE, COHERENCE],
|
|
92
|
+
"consolidation": [COHERENCE, SILENCE, RECURSIVITY],
|
|
93
|
+
"mutation": [COHERENCE, MUTATION, TRANSITION, COHERENCE],
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# Performance history: sequence_name -> [coherence_gains]
|
|
97
|
+
self.performance: Dict[str, List[float]] = {
|
|
98
|
+
k: [] for k in self.sequences.keys()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
def select_sequence(self, context: Dict[str, Any]) -> List[str]:
|
|
102
|
+
"""Select optimal sequence based on context and historical performance.
|
|
103
|
+
|
|
104
|
+
Uses goal-based filtering and epsilon-greedy selection:
|
|
105
|
+
|
|
106
|
+
1. Filter sequences appropriate for goal
|
|
107
|
+
2. With probability 0.8: select best-performing sequence
|
|
108
|
+
3. With probability 0.2: select random sequence (exploration)
|
|
109
|
+
|
|
110
|
+
Parameters
|
|
111
|
+
----------
|
|
112
|
+
context : dict
|
|
113
|
+
Context with keys:
|
|
114
|
+
|
|
115
|
+
- **goal** (str): "stability", "growth", or "adaptation"
|
|
116
|
+
- **urgency** (float): Urgency level (0-1), currently unused
|
|
117
|
+
|
|
118
|
+
Returns
|
|
119
|
+
-------
|
|
120
|
+
list[str]
|
|
121
|
+
Sequence of operator names to execute
|
|
122
|
+
|
|
123
|
+
Notes
|
|
124
|
+
-----
|
|
125
|
+
Goal-to-sequence mapping follows TNFR principles:
|
|
126
|
+
|
|
127
|
+
- **stability**: Sequences emphasizing IL (Coherence) and SHA (Silence)
|
|
128
|
+
- **growth**: Sequences with AL (Emission) and THOL (Self-organization)
|
|
129
|
+
- **adaptation**: Sequences with ZHIR (Mutation) and learning cycles
|
|
130
|
+
"""
|
|
131
|
+
goal = context.get("goal", "stability")
|
|
132
|
+
|
|
133
|
+
# Map goals to appropriate sequence candidates
|
|
134
|
+
if goal == "stability":
|
|
135
|
+
candidates = ["basic_activation", "consolidation"]
|
|
136
|
+
elif goal == "growth":
|
|
137
|
+
candidates = ["deep_learning", "exploration"]
|
|
138
|
+
elif goal == "adaptation":
|
|
139
|
+
candidates = ["mutation", "deep_learning"]
|
|
140
|
+
else:
|
|
141
|
+
candidates = list(self.sequences.keys())
|
|
142
|
+
|
|
143
|
+
# Epsilon-greedy selection (20% exploration, 80% exploitation)
|
|
144
|
+
epsilon = 0.2
|
|
145
|
+
|
|
146
|
+
if np is not None:
|
|
147
|
+
random_val = np.random.random()
|
|
148
|
+
else:
|
|
149
|
+
random_val = random.random()
|
|
150
|
+
|
|
151
|
+
if random_val < epsilon:
|
|
152
|
+
# Exploration: random selection
|
|
153
|
+
if np is not None:
|
|
154
|
+
selected = str(np.random.choice(candidates))
|
|
155
|
+
else:
|
|
156
|
+
selected = random.choice(candidates)
|
|
157
|
+
else:
|
|
158
|
+
# Exploitation: select best-performing sequence
|
|
159
|
+
avg_perf = {
|
|
160
|
+
k: (
|
|
161
|
+
sum(self.performance[k]) / len(self.performance[k])
|
|
162
|
+
if self.performance[k]
|
|
163
|
+
else 0.0
|
|
164
|
+
)
|
|
165
|
+
for k in candidates
|
|
166
|
+
}
|
|
167
|
+
selected = max(avg_perf, key=avg_perf.get) # type: ignore[arg-type]
|
|
168
|
+
|
|
169
|
+
return self.sequences[selected]
|
|
170
|
+
|
|
171
|
+
def record_performance(self, sequence_name: str, coherence_gain: float) -> None:
|
|
172
|
+
"""Record performance metric for a sequence to enable learning.
|
|
173
|
+
|
|
174
|
+
Parameters
|
|
175
|
+
----------
|
|
176
|
+
sequence_name : str
|
|
177
|
+
Name of the sequence that was executed
|
|
178
|
+
coherence_gain : float
|
|
179
|
+
Achieved coherence improvement or other performance metric
|
|
180
|
+
|
|
181
|
+
Notes
|
|
182
|
+
-----
|
|
183
|
+
Maintains a sliding window of the last 20 executions to adapt to
|
|
184
|
+
changing dynamics. Older performance data is discarded.
|
|
185
|
+
"""
|
|
186
|
+
if sequence_name in self.performance:
|
|
187
|
+
self.performance[sequence_name].append(float(coherence_gain))
|
|
188
|
+
# Keep only last 20 executions (sliding window)
|
|
189
|
+
self.performance[sequence_name] = self.performance[sequence_name][-20:]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Type stubs for tnfr.dynamics.adaptive_sequences module."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, List
|
|
4
|
+
from ..types import TNFRGraph, NodeId
|
|
5
|
+
|
|
6
|
+
class AdaptiveSequenceSelector:
|
|
7
|
+
G: TNFRGraph
|
|
8
|
+
node: NodeId
|
|
9
|
+
sequences: Dict[str, List[str]]
|
|
10
|
+
performance: Dict[str, List[float]]
|
|
11
|
+
|
|
12
|
+
def __init__(self, graph: TNFRGraph, node: NodeId) -> None: ...
|
|
13
|
+
def select_sequence(self, context: Dict[str, Any]) -> List[str]: ...
|
|
14
|
+
def record_performance(self, sequence_name: str, coherence_gain: float) -> None: ...
|
tnfr/dynamics/aliases.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Shared alias tokens used across TNFR dynamics submodules."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ..constants.aliases import (
|
|
6
|
+
ALIAS_D2EPI,
|
|
7
|
+
ALIAS_DNFR,
|
|
8
|
+
ALIAS_DSI,
|
|
9
|
+
ALIAS_EPI,
|
|
10
|
+
ALIAS_SI,
|
|
11
|
+
ALIAS_THETA,
|
|
12
|
+
ALIAS_VF,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = (
|
|
16
|
+
"ALIAS_VF",
|
|
17
|
+
"ALIAS_DNFR",
|
|
18
|
+
"ALIAS_EPI",
|
|
19
|
+
"ALIAS_SI",
|
|
20
|
+
"ALIAS_THETA",
|
|
21
|
+
"ALIAS_D2EPI",
|
|
22
|
+
"ALIAS_DSI",
|
|
23
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from ..constants.aliases import (
|
|
2
|
+
ALIAS_D2EPI as ALIAS_D2EPI,
|
|
3
|
+
ALIAS_DNFR as ALIAS_DNFR,
|
|
4
|
+
ALIAS_DSI as ALIAS_DSI,
|
|
5
|
+
ALIAS_EPI as ALIAS_EPI,
|
|
6
|
+
ALIAS_SI as ALIAS_SI,
|
|
7
|
+
ALIAS_THETA as ALIAS_THETA,
|
|
8
|
+
ALIAS_VF as ALIAS_VF,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"ALIAS_VF",
|
|
13
|
+
"ALIAS_DNFR",
|
|
14
|
+
"ALIAS_EPI",
|
|
15
|
+
"ALIAS_SI",
|
|
16
|
+
"ALIAS_THETA",
|
|
17
|
+
"ALIAS_D2EPI",
|
|
18
|
+
"ALIAS_DSI",
|
|
19
|
+
]
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"""Bifurcation dynamics and structural path selection for TNFR operators.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for detecting bifurcation readiness and
|
|
4
|
+
determining viable structural reorganization paths after OZ-induced dissonance.
|
|
5
|
+
|
|
6
|
+
According to TNFR canonical theory (§2.3.3, R4), when ∂²EPI/∂t² > τ,
|
|
7
|
+
the system enters a bifurcation state enabling multiple reorganization
|
|
8
|
+
trajectories. This module implements path selection based on nodal state.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from ..types import Glyph, NodeId, TNFRGraph
|
|
17
|
+
|
|
18
|
+
from ..alias import get_attr
|
|
19
|
+
from ..constants.aliases import ALIAS_DNFR, ALIAS_EPI, ALIAS_VF
|
|
20
|
+
from ..types import Glyph
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"get_bifurcation_paths",
|
|
24
|
+
"compute_bifurcation_score",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_bifurcation_paths(G: "TNFRGraph", node: "NodeId") -> list["Glyph"]:
|
|
29
|
+
"""Return viable structural paths after OZ-induced bifurcation.
|
|
30
|
+
|
|
31
|
+
When OZ (Dissonance) creates bifurcation readiness (∂²EPI/∂t² > τ),
|
|
32
|
+
this function determines which operators can resolve the dissonance
|
|
33
|
+
based on current nodal state.
|
|
34
|
+
|
|
35
|
+
Parameters
|
|
36
|
+
----------
|
|
37
|
+
G : TNFRGraph
|
|
38
|
+
Graph containing the node
|
|
39
|
+
node : NodeId
|
|
40
|
+
Node identifier
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
list[Glyph]
|
|
45
|
+
List of viable operator glyphs for structural reorganization.
|
|
46
|
+
Empty list if node is not in bifurcation state.
|
|
47
|
+
|
|
48
|
+
Notes
|
|
49
|
+
-----
|
|
50
|
+
**Canonical bifurcation paths:**
|
|
51
|
+
|
|
52
|
+
- **ZHIR (Mutation)**: Viable if νf > 0.8 (sufficient for controlled transformation)
|
|
53
|
+
- **NUL (Contraction)**: Viable if EPI < 0.5 (safe collapse window)
|
|
54
|
+
- **IL (Coherence)**: Always viable (universal resolution path)
|
|
55
|
+
- **THOL (Self-organization)**: Viable if degree >= 2 (network support)
|
|
56
|
+
|
|
57
|
+
The node must have `_bifurcation_ready = True` flag, typically set by
|
|
58
|
+
OZ precondition validation when ∂²EPI/∂t² exceeds threshold τ.
|
|
59
|
+
|
|
60
|
+
Examples
|
|
61
|
+
--------
|
|
62
|
+
>>> from tnfr.structural import create_nfr
|
|
63
|
+
>>> from tnfr.operators.definitions import Dissonance
|
|
64
|
+
>>> from tnfr.dynamics.bifurcation import get_bifurcation_paths
|
|
65
|
+
>>> G, node = create_nfr("test", epi=0.4, vf=1.0)
|
|
66
|
+
>>> # Set up bifurcation conditions
|
|
67
|
+
>>> G.nodes[node]["epi_history"] = [0.2, 0.35, 0.55]
|
|
68
|
+
>>> Dissonance()(G, node, validate_preconditions=True)
|
|
69
|
+
>>> paths = get_bifurcation_paths(G, node)
|
|
70
|
+
>>> # Returns viable operators: [ZHIR, NUL, IL, THOL] or subset
|
|
71
|
+
|
|
72
|
+
See Also
|
|
73
|
+
--------
|
|
74
|
+
tnfr.operators.preconditions.validate_dissonance : Sets bifurcation_ready flag
|
|
75
|
+
tnfr.operators.definitions.SelfOrganization : Spawns sub-EPIs on bifurcation
|
|
76
|
+
"""
|
|
77
|
+
# Check if bifurcation active
|
|
78
|
+
if not G.nodes[node].get("_bifurcation_ready", False):
|
|
79
|
+
return [] # No bifurcation active
|
|
80
|
+
|
|
81
|
+
# Get node state for path evaluation
|
|
82
|
+
dnfr = abs(float(get_attr(G.nodes[node], ALIAS_DNFR, 0.0)))
|
|
83
|
+
epi = float(get_attr(G.nodes[node], ALIAS_EPI, 0.0))
|
|
84
|
+
vf = float(get_attr(G.nodes[node], ALIAS_VF, 0.0))
|
|
85
|
+
degree = G.degree(node)
|
|
86
|
+
|
|
87
|
+
paths = []
|
|
88
|
+
|
|
89
|
+
# ZHIR (Mutation) viable if sufficient νf for controlled transformation
|
|
90
|
+
zhir_threshold = float(G.graph.get("ZHIR_BIFURCATION_VF_THRESHOLD", 0.8))
|
|
91
|
+
if vf > zhir_threshold:
|
|
92
|
+
paths.append(Glyph.ZHIR)
|
|
93
|
+
|
|
94
|
+
# NUL (Contraction) viable if EPI low enough for safe collapse
|
|
95
|
+
nul_threshold = float(G.graph.get("NUL_BIFURCATION_EPI_THRESHOLD", 0.5))
|
|
96
|
+
if epi < nul_threshold:
|
|
97
|
+
paths.append(Glyph.NUL)
|
|
98
|
+
|
|
99
|
+
# IL (Coherence) always viable as universal resolution path
|
|
100
|
+
paths.append(Glyph.IL)
|
|
101
|
+
|
|
102
|
+
# THOL (Self-organization) viable if network connectivity supports it
|
|
103
|
+
thol_min_degree = int(G.graph.get("THOL_BIFURCATION_MIN_DEGREE", 2))
|
|
104
|
+
if degree >= thol_min_degree:
|
|
105
|
+
paths.append(Glyph.THOL)
|
|
106
|
+
|
|
107
|
+
return paths
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def compute_bifurcation_score(
|
|
111
|
+
d2epi: float,
|
|
112
|
+
dnfr: float,
|
|
113
|
+
vf: float,
|
|
114
|
+
epi: float,
|
|
115
|
+
tau: float = 0.5,
|
|
116
|
+
) -> float:
|
|
117
|
+
"""Compute quantitative bifurcation potential [0,1].
|
|
118
|
+
|
|
119
|
+
Integrates multiple structural indicators to assess bifurcation readiness.
|
|
120
|
+
According to TNFR canonical theory (§2.3.3, R4), bifurcation occurs when
|
|
121
|
+
∂²EPI/∂t² > τ (acceleration exceeds threshold). This function extends that
|
|
122
|
+
binary condition into a continuous score that accounts for multiple factors.
|
|
123
|
+
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
d2epi : float
|
|
127
|
+
Structural acceleration (∂²EPI/∂t²). Primary indicator of bifurcation.
|
|
128
|
+
When |d2epi| > τ, the system enters a bifurcation state enabling
|
|
129
|
+
multiple reorganization trajectories.
|
|
130
|
+
dnfr : float
|
|
131
|
+
Internal reorganization operator (ΔNFR). Magnitude indicates instability
|
|
132
|
+
level. Higher |ΔNFR| means stronger reorganization pressure.
|
|
133
|
+
vf : float
|
|
134
|
+
Structural frequency (νf) in Hz_str units. Determines capacity to respond
|
|
135
|
+
to bifurcation. Higher νf enables faster reorganization along new paths.
|
|
136
|
+
epi : float
|
|
137
|
+
Primary Information Structure. Provides structural substrate for
|
|
138
|
+
bifurcation. Higher EPI indicates more material to reorganize.
|
|
139
|
+
tau : float, default 0.5
|
|
140
|
+
Bifurcation acceleration threshold. When |d2epi| > tau, bifurcation
|
|
141
|
+
becomes active. Default 0.5 is the canonical TNFR threshold.
|
|
142
|
+
|
|
143
|
+
Returns
|
|
144
|
+
-------
|
|
145
|
+
float
|
|
146
|
+
Bifurcation score in range [0.0, 1.0]:
|
|
147
|
+
- 0.0 = no bifurcation potential (stable)
|
|
148
|
+
- 0.5 = bifurcation threshold (critical)
|
|
149
|
+
- 1.0 = maximal bifurcation readiness (multiple paths viable)
|
|
150
|
+
|
|
151
|
+
Notes
|
|
152
|
+
-----
|
|
153
|
+
The bifurcation score is a weighted combination of four factors:
|
|
154
|
+
|
|
155
|
+
1. **Acceleration factor** (40%): |∂²EPI/∂t²| / τ
|
|
156
|
+
Primary indicator. Measures how close the system is to or beyond
|
|
157
|
+
the bifurcation threshold.
|
|
158
|
+
|
|
159
|
+
2. **Instability factor** (30%): |ΔNFR|
|
|
160
|
+
Secondary indicator. Measures reorganization pressure that drives
|
|
161
|
+
bifurcation exploration.
|
|
162
|
+
|
|
163
|
+
3. **Capacity factor** (20%): νf / 2.0
|
|
164
|
+
Measures structural reorganization capacity. Higher νf enables faster
|
|
165
|
+
response to bifurcation opportunities.
|
|
166
|
+
|
|
167
|
+
4. **Substrate factor** (10%): EPI / 0.8
|
|
168
|
+
Measures available structural material. Higher EPI provides more
|
|
169
|
+
degrees of freedom for bifurcation paths.
|
|
170
|
+
|
|
171
|
+
Formula:
|
|
172
|
+
score = 0.4 * accel + 0.3 * instability + 0.2 * capacity + 0.1 * substrate
|
|
173
|
+
|
|
174
|
+
All factors are normalized to [0, 1] and clipped before combination.
|
|
175
|
+
|
|
176
|
+
Examples
|
|
177
|
+
--------
|
|
178
|
+
>>> from tnfr.dynamics.bifurcation import compute_bifurcation_score
|
|
179
|
+
>>>
|
|
180
|
+
>>> # Low bifurcation potential (stable state)
|
|
181
|
+
>>> score = compute_bifurcation_score(
|
|
182
|
+
... d2epi=0.1, # Low acceleration
|
|
183
|
+
... dnfr=0.05, # Low instability
|
|
184
|
+
... vf=0.5, # Moderate capacity
|
|
185
|
+
... epi=0.3, # Low substrate
|
|
186
|
+
... )
|
|
187
|
+
>>> assert score < 0.3 # Low score
|
|
188
|
+
>>>
|
|
189
|
+
>>> # High bifurcation potential (critical state)
|
|
190
|
+
>>> score = compute_bifurcation_score(
|
|
191
|
+
... d2epi=0.7, # High acceleration (> tau)
|
|
192
|
+
... dnfr=0.6, # High instability
|
|
193
|
+
... vf=1.8, # High capacity
|
|
194
|
+
... epi=0.7, # High substrate
|
|
195
|
+
... )
|
|
196
|
+
>>> assert score > 0.7 # High score
|
|
197
|
+
|
|
198
|
+
See Also
|
|
199
|
+
--------
|
|
200
|
+
get_bifurcation_paths : Determine viable operators after bifurcation
|
|
201
|
+
tnfr.operators.metrics.dissonance_metrics : Uses score in OZ metrics
|
|
202
|
+
"""
|
|
203
|
+
from ..utils import get_numpy
|
|
204
|
+
|
|
205
|
+
np = get_numpy()
|
|
206
|
+
|
|
207
|
+
# 1. Acceleration factor (primary indicator)
|
|
208
|
+
# Normalized by tau threshold
|
|
209
|
+
accel_factor = min(abs(d2epi) / tau, 1.0) if tau > 0 else 0.0
|
|
210
|
+
|
|
211
|
+
# 2. Instability factor (secondary indicator)
|
|
212
|
+
# Already dimensionless, clip to [0, 1]
|
|
213
|
+
instability_factor = min(abs(dnfr), 1.0)
|
|
214
|
+
|
|
215
|
+
# 3. Capacity factor (reorganization capability)
|
|
216
|
+
# Normalize by 2.0 (typical high νf value)
|
|
217
|
+
capacity_factor = min(vf / 2.0, 1.0) if vf >= 0 else 0.0
|
|
218
|
+
|
|
219
|
+
# 4. Substrate factor (structural material available)
|
|
220
|
+
# Normalize by 0.8 (typical high EPI value)
|
|
221
|
+
substrate_factor = min(epi / 0.8, 1.0) if epi >= 0 else 0.0
|
|
222
|
+
|
|
223
|
+
# Weighted combination (percentages sum to 100%)
|
|
224
|
+
score = (
|
|
225
|
+
0.4 * accel_factor # 40% - primary
|
|
226
|
+
+ 0.3 * instability_factor # 30% - secondary
|
|
227
|
+
+ 0.2 * capacity_factor # 20% - capability
|
|
228
|
+
+ 0.1 * substrate_factor # 10% - material
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
# Ensure result is in [0, 1] range
|
|
232
|
+
return float(np.clip(score, 0.0, 1.0))
|