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,38 @@
|
|
|
1
|
+
"""Postcondition validators for TNFR structural operators.
|
|
2
|
+
|
|
3
|
+
Each operator has specific guarantees that must be verified after execution
|
|
4
|
+
to ensure TNFR structural invariants are maintained. This package provides
|
|
5
|
+
postcondition validators for operators that need strict verification.
|
|
6
|
+
|
|
7
|
+
Postconditions ensure that operators fulfill their contracts and maintain
|
|
8
|
+
canonical TNFR physics.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from ...types import NodeId, TNFRGraph
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"OperatorContractViolation",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class OperatorContractViolation(Exception):
|
|
24
|
+
"""Raised when an operator's postconditions are violated."""
|
|
25
|
+
|
|
26
|
+
def __init__(self, operator: str, reason: str) -> None:
|
|
27
|
+
"""Initialize contract violation error.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
operator : str
|
|
32
|
+
Name of the operator that violated its contract
|
|
33
|
+
reason : str
|
|
34
|
+
Description of why the contract was violated
|
|
35
|
+
"""
|
|
36
|
+
self.operator = operator
|
|
37
|
+
self.reason = reason
|
|
38
|
+
super().__init__(f"{operator} contract violation: {reason}")
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"""Postcondition validators for ZHIR (Mutation) operator.
|
|
2
|
+
|
|
3
|
+
Implements verification of mutation postconditions including phase transformation,
|
|
4
|
+
identity preservation, and bifurcation handling.
|
|
5
|
+
|
|
6
|
+
These postconditions ensure that ZHIR fulfills its contract and maintains TNFR
|
|
7
|
+
structural invariants.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from ...types import NodeId, TNFRGraph
|
|
16
|
+
|
|
17
|
+
from ...alias import get_attr
|
|
18
|
+
from ...constants.aliases import ALIAS_THETA
|
|
19
|
+
from . import OperatorContractViolation
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"verify_phase_transformed",
|
|
23
|
+
"verify_identity_preserved",
|
|
24
|
+
"verify_bifurcation_handled",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def verify_phase_transformed(
|
|
29
|
+
G: TNFRGraph, node: NodeId, theta_before: float
|
|
30
|
+
) -> None:
|
|
31
|
+
"""Verify that phase was actually transformed by ZHIR.
|
|
32
|
+
|
|
33
|
+
ZHIR's primary contract is phase transformation (θ → θ'). This verifies
|
|
34
|
+
that the phase actually changed, fulfilling the operator's purpose.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
G : TNFRGraph
|
|
39
|
+
Graph containing the node
|
|
40
|
+
node : NodeId
|
|
41
|
+
Node to verify
|
|
42
|
+
theta_before : float
|
|
43
|
+
Phase value before ZHIR application
|
|
44
|
+
|
|
45
|
+
Raises
|
|
46
|
+
------
|
|
47
|
+
OperatorContractViolation
|
|
48
|
+
If phase was not transformed (theta unchanged)
|
|
49
|
+
|
|
50
|
+
Notes
|
|
51
|
+
-----
|
|
52
|
+
A small tolerance (1e-6) is used to account for floating-point precision.
|
|
53
|
+
If theta changes by less than this tolerance, it's considered unchanged.
|
|
54
|
+
|
|
55
|
+
This check ensures that ZHIR actually performs its structural transformation
|
|
56
|
+
rather than being a no-op.
|
|
57
|
+
|
|
58
|
+
Examples
|
|
59
|
+
--------
|
|
60
|
+
>>> from tnfr.structural import create_nfr
|
|
61
|
+
>>> from tnfr.operators import Mutation
|
|
62
|
+
>>> G, node = create_nfr("test", epi=0.5, vf=1.0, theta=0.0)
|
|
63
|
+
>>> theta_before = G.nodes[node]["theta"]
|
|
64
|
+
>>> Mutation()(G, node)
|
|
65
|
+
>>> verify_phase_transformed(G, node, theta_before) # Should pass
|
|
66
|
+
"""
|
|
67
|
+
theta_after = float(get_attr(G.nodes[node], ALIAS_THETA, 0.0))
|
|
68
|
+
|
|
69
|
+
# Check if phase actually changed (with small tolerance for floating-point)
|
|
70
|
+
if abs(theta_after - theta_before) < 1e-6:
|
|
71
|
+
raise OperatorContractViolation(
|
|
72
|
+
"Mutation",
|
|
73
|
+
f"Phase was not transformed (θ before={theta_before:.6f}, "
|
|
74
|
+
f"θ after={theta_after:.6f}, diff={abs(theta_after - theta_before):.9f}). "
|
|
75
|
+
f"ZHIR must transform phase to fulfill its contract."
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def verify_identity_preserved(
|
|
80
|
+
G: TNFRGraph, node: NodeId, epi_kind_before: str | None
|
|
81
|
+
) -> None:
|
|
82
|
+
"""Verify that structural identity (epi_kind) was preserved through mutation.
|
|
83
|
+
|
|
84
|
+
ZHIR transforms phase/regime while preserving structural identity. A cell
|
|
85
|
+
remains a cell, a concept remains a concept - only the operational mode changes.
|
|
86
|
+
This is a fundamental TNFR invariant: transformations preserve coherence.
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
----------
|
|
90
|
+
G : TNFRGraph
|
|
91
|
+
Graph containing the node
|
|
92
|
+
node : NodeId
|
|
93
|
+
Node to verify
|
|
94
|
+
epi_kind_before : str or None
|
|
95
|
+
Identity (epi_kind) before ZHIR application
|
|
96
|
+
|
|
97
|
+
Raises
|
|
98
|
+
------
|
|
99
|
+
OperatorContractViolation
|
|
100
|
+
If identity changed during mutation
|
|
101
|
+
|
|
102
|
+
Notes
|
|
103
|
+
-----
|
|
104
|
+
If epi_kind_before is None (identity not tracked), this check is skipped.
|
|
105
|
+
This allows flexibility for simple nodes while enforcing identity preservation
|
|
106
|
+
when it's explicitly tracked.
|
|
107
|
+
|
|
108
|
+
**Special Case**: If epi_kind is used to track operator glyphs (common pattern),
|
|
109
|
+
the check is skipped since this is operational metadata, not structural identity.
|
|
110
|
+
To enable strict identity checking, use a separate attribute (e.g., "structural_type"
|
|
111
|
+
or "node_type") for identity tracking.
|
|
112
|
+
|
|
113
|
+
Identity preservation is distinct from EPI preservation - EPI may change
|
|
114
|
+
slightly during mutation (structural adjustments), but the fundamental type
|
|
115
|
+
(epi_kind) must remain constant.
|
|
116
|
+
|
|
117
|
+
Examples
|
|
118
|
+
--------
|
|
119
|
+
>>> from tnfr.structural import create_nfr
|
|
120
|
+
>>> from tnfr.operators import Mutation
|
|
121
|
+
>>> G, node = create_nfr("test", epi=0.5, vf=1.0)
|
|
122
|
+
>>> G.nodes[node]["structural_type"] = "stem_cell" # Use separate attribute
|
|
123
|
+
>>> epi_kind_before = G.nodes[node]["structural_type"]
|
|
124
|
+
>>> Mutation()(G, node)
|
|
125
|
+
>>> # After mutation, structural_type should still be "stem_cell"
|
|
126
|
+
>>> # verify_identity_preserved(G, node, epi_kind_before) # Would check structural_type
|
|
127
|
+
"""
|
|
128
|
+
# Skip check if identity was not tracked
|
|
129
|
+
if epi_kind_before is None:
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
epi_kind_after = G.nodes[node].get("epi_kind")
|
|
133
|
+
|
|
134
|
+
# Skip if epi_kind appears to be tracking operator glyphs (common pattern)
|
|
135
|
+
# Operator glyphs are short codes like "IL", "OZ", "ZHIR"
|
|
136
|
+
if epi_kind_after in ["IL", "EN", "AL", "OZ", "RA", "UM", "SHA", "VAL", "NUL", "THOL", "ZHIR", "NAV", "REMESH"]:
|
|
137
|
+
# epi_kind is being used for operator tracking, not identity
|
|
138
|
+
# This is acceptable operational metadata, skip identity check
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
if epi_kind_after != epi_kind_before:
|
|
142
|
+
raise OperatorContractViolation(
|
|
143
|
+
"Mutation",
|
|
144
|
+
f"Structural identity changed during mutation: "
|
|
145
|
+
f"{epi_kind_before} → {epi_kind_after}. "
|
|
146
|
+
f"ZHIR must preserve epi_kind while transforming phase."
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def verify_bifurcation_handled(G: TNFRGraph, node: NodeId) -> None:
|
|
151
|
+
"""Verify that bifurcation was handled if triggered during mutation.
|
|
152
|
+
|
|
153
|
+
When ZHIR detects bifurcation potential (∂²EPI/∂t² > τ), it must either:
|
|
154
|
+
1. Create a variant node (if bifurcation mode = "variant_creation")
|
|
155
|
+
2. Set detection flag (if bifurcation mode = "detection")
|
|
156
|
+
|
|
157
|
+
This ensures that bifurcation events are properly tracked and controlled,
|
|
158
|
+
preventing uncontrolled structural fragmentation.
|
|
159
|
+
|
|
160
|
+
Parameters
|
|
161
|
+
----------
|
|
162
|
+
G : TNFRGraph
|
|
163
|
+
Graph containing the node
|
|
164
|
+
node : NodeId
|
|
165
|
+
Node to verify
|
|
166
|
+
|
|
167
|
+
Raises
|
|
168
|
+
------
|
|
169
|
+
OperatorContractViolation
|
|
170
|
+
If bifurcation was triggered but not handled according to configured mode
|
|
171
|
+
|
|
172
|
+
Notes
|
|
173
|
+
-----
|
|
174
|
+
**Bifurcation Modes**:
|
|
175
|
+
|
|
176
|
+
- "detection" (default): Only flag bifurcation potential, no variant creation
|
|
177
|
+
- "variant_creation": Create new node as bifurcation variant
|
|
178
|
+
|
|
179
|
+
In "variant_creation" mode, the function verifies that a bifurcation event
|
|
180
|
+
was recorded in G.graph["zhir_bifurcation_events"].
|
|
181
|
+
|
|
182
|
+
Grammar rule U4a requires bifurcation handlers (THOL or IL) after ZHIR
|
|
183
|
+
when bifurcation is detected.
|
|
184
|
+
|
|
185
|
+
Examples
|
|
186
|
+
--------
|
|
187
|
+
>>> from tnfr.structural import create_nfr
|
|
188
|
+
>>> from tnfr.operators import Mutation
|
|
189
|
+
>>> G, node = create_nfr("test", epi=0.5, vf=1.0)
|
|
190
|
+
>>> G.graph["ZHIR_BIFURCATION_MODE"] = "detection"
|
|
191
|
+
>>> Mutation()(G, node)
|
|
192
|
+
>>> # If bifurcation detected, flag should be set
|
|
193
|
+
>>> verify_bifurcation_handled(G, node) # Should pass
|
|
194
|
+
"""
|
|
195
|
+
# Check if bifurcation was detected
|
|
196
|
+
bifurcation_potential = G.nodes[node].get("_zhir_bifurcation_potential", False)
|
|
197
|
+
|
|
198
|
+
if not bifurcation_potential:
|
|
199
|
+
# No bifurcation detected, nothing to verify
|
|
200
|
+
return
|
|
201
|
+
|
|
202
|
+
# Bifurcation was detected - verify it was handled
|
|
203
|
+
mode = G.graph.get("ZHIR_BIFURCATION_MODE", "detection")
|
|
204
|
+
|
|
205
|
+
if mode == "variant_creation":
|
|
206
|
+
# In variant creation mode, verify variant was actually created
|
|
207
|
+
events = G.graph.get("zhir_bifurcation_events", [])
|
|
208
|
+
|
|
209
|
+
# Check if this node has a recorded bifurcation event
|
|
210
|
+
node_has_event = any(
|
|
211
|
+
event.get("parent_node") == node
|
|
212
|
+
for event in events
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
if not node_has_event:
|
|
216
|
+
raise OperatorContractViolation(
|
|
217
|
+
"Mutation",
|
|
218
|
+
f"Bifurcation potential detected (∂²EPI/∂t² > τ) but variant "
|
|
219
|
+
f"was not created. Mode={mode} requires variant creation. "
|
|
220
|
+
f"Check _spawn_mutation_variant() implementation."
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
elif mode == "detection":
|
|
224
|
+
# In detection mode, just verify the flag is set (already checked above)
|
|
225
|
+
# No variant creation required, flag is sufficient
|
|
226
|
+
pass
|
|
227
|
+
|
|
228
|
+
else:
|
|
229
|
+
# Unknown mode - log warning but don't raise error
|
|
230
|
+
import warnings
|
|
231
|
+
warnings.warn(
|
|
232
|
+
f"Unknown ZHIR_BIFURCATION_MODE: {mode}. "
|
|
233
|
+
f"Expected 'detection' or 'variant_creation'. "
|
|
234
|
+
f"Bifurcation handling could not be fully verified.",
|
|
235
|
+
stacklevel=2,
|
|
236
|
+
)
|