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
|
@@ -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))
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"""Canonical TNFR nodal equation implementation.
|
|
2
|
+
|
|
3
|
+
This module provides the explicit, canonical implementation of the fundamental
|
|
4
|
+
TNFR nodal equation as specified in the theory:
|
|
5
|
+
|
|
6
|
+
∂EPI/∂t = νf · ΔNFR(t)
|
|
7
|
+
|
|
8
|
+
Where:
|
|
9
|
+
- EPI: Primary Information Structure (coherent form)
|
|
10
|
+
- νf: Structural frequency in Hz_str (structural hertz)
|
|
11
|
+
- ΔNFR: Nodal gradient (reorganization operator)
|
|
12
|
+
- t: Structural time (not chronological time)
|
|
13
|
+
|
|
14
|
+
This implementation ensures theoretical fidelity to the TNFR paradigm by:
|
|
15
|
+
1. Making the canonical equation explicit in code
|
|
16
|
+
2. Validating dimensional consistency (Hz_str units)
|
|
17
|
+
3. Providing clear mapping between theory and implementation
|
|
18
|
+
4. Maintaining reproducibility and traceability
|
|
19
|
+
|
|
20
|
+
TNFR Invariants (from AGENTS.md):
|
|
21
|
+
- EPI as coherent form: changes only via structural operators
|
|
22
|
+
- Structural units: νf expressed in Hz_str (structural hertz)
|
|
23
|
+
- ΔNFR semantics: sign and magnitude modulate reorganization rate
|
|
24
|
+
- Operator closure: composition yields valid TNFR states
|
|
25
|
+
|
|
26
|
+
References:
|
|
27
|
+
- TNFR.pdf: Canonical nodal equation specification
|
|
28
|
+
- AGENTS.md: Section 3 (Canonical invariants)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import math
|
|
34
|
+
from typing import TYPE_CHECKING, NamedTuple
|
|
35
|
+
|
|
36
|
+
if TYPE_CHECKING:
|
|
37
|
+
from ..types import GraphLike
|
|
38
|
+
|
|
39
|
+
__all__ = (
|
|
40
|
+
"NodalEquationResult",
|
|
41
|
+
"compute_canonical_nodal_derivative",
|
|
42
|
+
"validate_structural_frequency",
|
|
43
|
+
"validate_nodal_gradient",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class NodalEquationResult(NamedTuple):
|
|
48
|
+
"""Result of canonical nodal equation evaluation.
|
|
49
|
+
|
|
50
|
+
Attributes:
|
|
51
|
+
derivative: ∂EPI/∂t computed from νf · ΔNFR(t)
|
|
52
|
+
nu_f: Structural frequency (Hz_str) used in computation
|
|
53
|
+
delta_nfr: Nodal gradient (ΔNFR) used in computation
|
|
54
|
+
validated: Whether units and bounds were validated
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
derivative: float
|
|
58
|
+
nu_f: float
|
|
59
|
+
delta_nfr: float
|
|
60
|
+
validated: bool
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def compute_canonical_nodal_derivative(
|
|
64
|
+
nu_f: float,
|
|
65
|
+
delta_nfr: float,
|
|
66
|
+
*,
|
|
67
|
+
validate_units: bool = True,
|
|
68
|
+
graph: GraphLike | None = None,
|
|
69
|
+
) -> NodalEquationResult:
|
|
70
|
+
"""Compute ∂EPI/∂t using the canonical TNFR nodal equation.
|
|
71
|
+
|
|
72
|
+
This is the explicit implementation of the fundamental equation:
|
|
73
|
+
∂EPI/∂t = νf · ΔNFR(t)
|
|
74
|
+
|
|
75
|
+
The function computes the time derivative of the Primary Information
|
|
76
|
+
Structure (EPI) as the product of:
|
|
77
|
+
- νf: structural frequency (reorganization rate in Hz_str)
|
|
78
|
+
- ΔNFR: nodal gradient (reorganization need/operator)
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
nu_f: Structural frequency in Hz_str (must be non-negative)
|
|
82
|
+
delta_nfr: Nodal gradient (reorganization operator)
|
|
83
|
+
validate_units: If True, validates that inputs are in valid ranges
|
|
84
|
+
graph: Optional graph for context-aware validation
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
NodalEquationResult containing the computed derivative and metadata
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
ValueError: If validation is enabled and inputs are invalid
|
|
91
|
+
|
|
92
|
+
Notes:
|
|
93
|
+
- This function is the canonical reference implementation
|
|
94
|
+
- The result represents the instantaneous rate of EPI evolution
|
|
95
|
+
- Units: [∂EPI/∂t] = Hz_str (structural reorganization rate)
|
|
96
|
+
- The product νf·ΔNFR must preserve TNFR operator closure
|
|
97
|
+
|
|
98
|
+
Examples:
|
|
99
|
+
>>> # Basic computation
|
|
100
|
+
>>> result = compute_canonical_nodal_derivative(1.0, 0.5)
|
|
101
|
+
>>> result.derivative
|
|
102
|
+
0.5
|
|
103
|
+
|
|
104
|
+
>>> # With explicit validation
|
|
105
|
+
>>> result = compute_canonical_nodal_derivative(
|
|
106
|
+
... nu_f=1.2,
|
|
107
|
+
... delta_nfr=-0.3,
|
|
108
|
+
... validate_units=True
|
|
109
|
+
... )
|
|
110
|
+
>>> result.validated
|
|
111
|
+
True
|
|
112
|
+
"""
|
|
113
|
+
validated = False
|
|
114
|
+
|
|
115
|
+
if validate_units:
|
|
116
|
+
nu_f = validate_structural_frequency(nu_f, graph=graph)
|
|
117
|
+
delta_nfr = validate_nodal_gradient(delta_nfr, graph=graph)
|
|
118
|
+
validated = True
|
|
119
|
+
|
|
120
|
+
# Canonical TNFR nodal equation: ∂EPI/∂t = νf · ΔNFR(t)
|
|
121
|
+
derivative = float(nu_f) * float(delta_nfr)
|
|
122
|
+
|
|
123
|
+
return NodalEquationResult(
|
|
124
|
+
derivative=derivative,
|
|
125
|
+
nu_f=nu_f,
|
|
126
|
+
delta_nfr=delta_nfr,
|
|
127
|
+
validated=validated,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def validate_structural_frequency(
|
|
132
|
+
nu_f: float,
|
|
133
|
+
*,
|
|
134
|
+
graph: GraphLike | None = None,
|
|
135
|
+
) -> float:
|
|
136
|
+
"""Validate that structural frequency is in valid range.
|
|
137
|
+
|
|
138
|
+
Structural frequency (νf) must satisfy TNFR constraints:
|
|
139
|
+
- Non-negative (νf ≥ 0)
|
|
140
|
+
- Expressed in Hz_str (structural hertz)
|
|
141
|
+
- Finite and well-defined
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
nu_f: Structural frequency to validate
|
|
145
|
+
graph: Optional graph for context-aware bounds checking
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Validated structural frequency value
|
|
149
|
+
|
|
150
|
+
Raises:
|
|
151
|
+
ValueError: If nu_f is negative, infinite, or NaN
|
|
152
|
+
TypeError: If nu_f cannot be converted to float
|
|
153
|
+
|
|
154
|
+
Notes:
|
|
155
|
+
- νf = 0 is valid and represents structural silence
|
|
156
|
+
- Units must be Hz_str (not classical Hz)
|
|
157
|
+
- For Hz↔Hz_str conversion, use tnfr.units module
|
|
158
|
+
"""
|
|
159
|
+
try:
|
|
160
|
+
value = float(nu_f)
|
|
161
|
+
except TypeError as exc:
|
|
162
|
+
# Non-convertible type (e.g., None, object())
|
|
163
|
+
raise TypeError(
|
|
164
|
+
f"Structural frequency must be numeric, got {type(nu_f).__name__}"
|
|
165
|
+
) from exc
|
|
166
|
+
except ValueError as exc:
|
|
167
|
+
# Invalid string value (e.g., "invalid")
|
|
168
|
+
raise ValueError(
|
|
169
|
+
f"Structural frequency must be a valid number, got {nu_f!r}"
|
|
170
|
+
) from exc
|
|
171
|
+
|
|
172
|
+
# Check for NaN or infinity using math.isfinite
|
|
173
|
+
if not math.isfinite(value):
|
|
174
|
+
raise ValueError(f"Structural frequency must be finite, got νf={value}")
|
|
175
|
+
|
|
176
|
+
if value < 0:
|
|
177
|
+
raise ValueError(f"Structural frequency must be non-negative, got νf={value}")
|
|
178
|
+
|
|
179
|
+
return value
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def validate_nodal_gradient(
|
|
183
|
+
delta_nfr: float,
|
|
184
|
+
*,
|
|
185
|
+
graph: GraphLike | None = None,
|
|
186
|
+
) -> float:
|
|
187
|
+
"""Validate that nodal gradient is well-defined.
|
|
188
|
+
|
|
189
|
+
The nodal gradient (ΔNFR) represents the internal reorganization
|
|
190
|
+
operator and must be:
|
|
191
|
+
- Finite and well-defined
|
|
192
|
+
- Sign indicates reorganization direction
|
|
193
|
+
- Magnitude indicates reorganization intensity
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
delta_nfr: Nodal gradient to validate
|
|
197
|
+
graph: Optional graph for context-aware validation
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
Validated nodal gradient value
|
|
201
|
+
|
|
202
|
+
Raises:
|
|
203
|
+
ValueError: If delta_nfr is infinite or NaN
|
|
204
|
+
TypeError: If delta_nfr cannot be converted to float
|
|
205
|
+
|
|
206
|
+
Notes:
|
|
207
|
+
- ΔNFR can be positive (expansion) or negative (contraction)
|
|
208
|
+
- ΔNFR = 0 indicates equilibrium (no reorganization)
|
|
209
|
+
- Do NOT reinterpret as classical "error gradient"
|
|
210
|
+
- Semantics: operator over EPI, not optimization target
|
|
211
|
+
"""
|
|
212
|
+
try:
|
|
213
|
+
value = float(delta_nfr)
|
|
214
|
+
except TypeError as exc:
|
|
215
|
+
# Non-convertible type (e.g., None, object())
|
|
216
|
+
raise TypeError(
|
|
217
|
+
f"Nodal gradient must be numeric, got {type(delta_nfr).__name__}"
|
|
218
|
+
) from exc
|
|
219
|
+
except ValueError as exc:
|
|
220
|
+
# Invalid string value (e.g., "invalid")
|
|
221
|
+
raise ValueError(
|
|
222
|
+
f"Nodal gradient must be a valid number, got {delta_nfr!r}"
|
|
223
|
+
) from exc
|
|
224
|
+
|
|
225
|
+
# Check for NaN or infinity using math.isfinite
|
|
226
|
+
if not math.isfinite(value):
|
|
227
|
+
raise ValueError(f"Nodal gradient must be finite, got ΔNFR={value}")
|
|
228
|
+
|
|
229
|
+
return value
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Type stubs for canonical TNFR nodal equation implementation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import NamedTuple
|
|
6
|
+
|
|
7
|
+
from ..types import GraphLike
|
|
8
|
+
|
|
9
|
+
__all__ = (
|
|
10
|
+
"NodalEquationResult",
|
|
11
|
+
"compute_canonical_nodal_derivative",
|
|
12
|
+
"validate_structural_frequency",
|
|
13
|
+
"validate_nodal_gradient",
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
class NodalEquationResult(NamedTuple):
|
|
17
|
+
"""Result of canonical nodal equation evaluation."""
|
|
18
|
+
|
|
19
|
+
derivative: float
|
|
20
|
+
nu_f: float
|
|
21
|
+
delta_nfr: float
|
|
22
|
+
validated: bool
|
|
23
|
+
|
|
24
|
+
def compute_canonical_nodal_derivative(
|
|
25
|
+
nu_f: float,
|
|
26
|
+
delta_nfr: float,
|
|
27
|
+
*,
|
|
28
|
+
validate_units: bool = True,
|
|
29
|
+
graph: GraphLike | None = None,
|
|
30
|
+
) -> NodalEquationResult:
|
|
31
|
+
"""Compute ∂EPI/∂t using the canonical TNFR nodal equation."""
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
def validate_structural_frequency(
|
|
35
|
+
nu_f: float,
|
|
36
|
+
*,
|
|
37
|
+
graph: GraphLike | None = None,
|
|
38
|
+
) -> float:
|
|
39
|
+
"""Validate that structural frequency is in valid range."""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
def validate_nodal_gradient(
|
|
43
|
+
delta_nfr: float,
|
|
44
|
+
*,
|
|
45
|
+
graph: GraphLike | None = None,
|
|
46
|
+
) -> float:
|
|
47
|
+
"""Validate that nodal gradient is well-defined."""
|
|
48
|
+
...
|