|
| 1 | +"""Algebraic properties and validation for TNFR structural operators. |
| 2 | +
|
| 3 | +Based on TNFR.pdf Section 3.2.4 - "Notación funcional de operadores glíficos". |
| 4 | +
|
| 5 | +This module implements formal validation of algebraic properties for structural |
| 6 | +operators in the TNFR glyphic algebra, particularly focusing on SHA (Silence) |
| 7 | +as the identity element in structural composition. |
| 8 | +
|
| 9 | +Theoretical Foundation |
| 10 | +---------------------- |
| 11 | +From TNFR.pdf §3.2.4 (p. 227-230) and the nodal equation ∂EPI/∂t = νf · ΔNFR(t): |
| 12 | +
|
| 13 | +1. **SHA as Structural Identity**: |
| 14 | + SHA(g(ω)) ≈ g(ω) for structure (EPI) |
| 15 | + |
| 16 | + Physical basis: SHA reduces νf → 0, making ∂EPI/∂t → 0. This freezes |
| 17 | + structural evolution, preserving whatever structure g created. |
| 18 | + |
| 19 | +2. **Idempotence**: |
| 20 | + SHA^n = SHA for all n ≥ 1 |
| 21 | + |
| 22 | + Physical basis: Once νf ≈ 0, further SHA applications cannot reduce it more. |
| 23 | + The effect is saturated. |
| 24 | + |
| 25 | +3. **Commutativity with NUL**: |
| 26 | + SHA ∘ NUL = NUL ∘ SHA |
| 27 | + |
| 28 | + Physical basis: SHA and NUL reduce orthogonal dimensions (νf vs EPI complexity). |
| 29 | + Order of reduction doesn't affect final state. |
| 30 | +
|
| 31 | +Category Theory Context |
| 32 | +----------------------- |
| 33 | +In the categorical framework (p. 231), SHA acts as identity morphism for |
| 34 | +the structural component: |
| 35 | +- Objects: Nodal configurations ω_i |
| 36 | +- Morphisms: Structural operators g: ω_i → ω_j |
| 37 | +- Identity: SHA: ω → ω (preserves structure) |
| 38 | +- Property: SHA ∘ g ≈ g (for EPI component) |
| 39 | +
|
| 40 | +Note: SHA is NOT full identity (it modifies νf). It's identity for the |
| 41 | +structural aspect (EPI), not the dynamic aspect (νf). |
| 42 | +""" |
| 43 | + |
| 44 | +from __future__ import annotations |
| 45 | + |
| 46 | +from typing import TYPE_CHECKING |
| 47 | + |
| 48 | +if TYPE_CHECKING: |
| 49 | + from ..types import TNFRGraph, NodeId |
| 50 | + from .definitions import Operator |
| 51 | + |
| 52 | +__all__ = [ |
| 53 | + "validate_identity_property", |
| 54 | + "validate_idempotence", |
| 55 | + "validate_commutativity_nul", |
| 56 | +] |
| 57 | + |
| 58 | + |
| 59 | +def validate_identity_property( |
| 60 | + G: TNFRGraph, |
| 61 | + node: NodeId, |
| 62 | + operator: Operator, |
| 63 | + tolerance: float = 0.01, |
| 64 | +) -> bool: |
| 65 | + """Validate that SHA acts as identity for structure after operator. |
| 66 | + |
| 67 | + Tests the algebraic property: SHA(g(ω)) ≈ g(ω) for EPI |
| 68 | + |
| 69 | + This validates that applying SHA preserves the structural state (EPI) |
| 70 | + achieved by the operator. SHA acts as a "pause" that freezes νf but |
| 71 | + does not alter the structural form EPI. |
| 72 | + |
| 73 | + Physical basis: From ∂EPI/∂t = νf · ΔNFR, when SHA reduces νf → 0, |
| 74 | + structural evolution stops but current structure is preserved. |
| 75 | + |
| 76 | + Parameters |
| 77 | + ---------- |
| 78 | + G : TNFRGraph |
| 79 | + Graph containing the node to validate |
| 80 | + node : NodeId |
| 81 | + Target node identifier |
| 82 | + operator : Operator |
| 83 | + Operator to test with SHA (must be valid generator like Emission) |
| 84 | + tolerance : float, optional |
| 85 | + Numerical tolerance for EPI comparison (default: 0.01) |
| 86 | + Relaxed due to grammar-required intermediate operators |
| 87 | + |
| 88 | + Returns |
| 89 | + ------- |
| 90 | + bool |
| 91 | + True if identity property holds within tolerance |
| 92 | + |
| 93 | + Notes |
| 94 | + ----- |
| 95 | + Due to TNFR grammar constraints (C1: must end with terminator, |
| 96 | + C2: must include stabilizer), we test identity by comparing: |
| 97 | + |
| 98 | + - Path 1: operator → Coherence → Dissonance (OZ terminator) |
| 99 | + - Path 2: operator → Coherence → Silence (SHA terminator) |
| 100 | + |
| 101 | + Both preserve structure after Coherence. If SHA is identity, |
| 102 | + EPI should be equivalent in both paths. |
| 103 | + |
| 104 | + Examples |
| 105 | + -------- |
| 106 | + >>> from tnfr.structural import create_nfr |
| 107 | + >>> from tnfr.operators.definitions import Emission |
| 108 | + >>> from tnfr.operators.algebra import validate_identity_property |
| 109 | + >>> G, node = create_nfr("test", epi=0.5, vf=1.0) |
| 110 | + >>> validate_identity_property(G, node, Emission()) # doctest: +SKIP |
| 111 | + True |
| 112 | + """ |
| 113 | + from ..alias import get_attr |
| 114 | + from ..constants.aliases import ALIAS_EPI |
| 115 | + from .definitions import Silence, Coherence, Dissonance |
| 116 | + from ..structural import run_sequence |
| 117 | + |
| 118 | + # Path 1: operator → Coherence → Dissonance (without SHA) |
| 119 | + # Valid grammar: generator → stabilizer → terminator |
| 120 | + G1 = G.copy() |
| 121 | + run_sequence(G1, node, [operator, Coherence(), Dissonance()]) |
| 122 | + epi_without_sha = float(get_attr(G1.nodes[node], ALIAS_EPI, 0.0)) |
| 123 | + |
| 124 | + # Path 2: operator → Coherence → Silence (SHA as terminator) |
| 125 | + # Valid grammar: generator → stabilizer → terminator |
| 126 | + G2 = G.copy() |
| 127 | + run_sequence(G2, node, [operator, Coherence(), Silence()]) |
| 128 | + epi_with_sha = float(get_attr(G2.nodes[node], ALIAS_EPI, 0.0)) |
| 129 | + |
| 130 | + # SHA should preserve the structural result (EPI) from operator → coherence |
| 131 | + # Both terminators should leave structure intact after stabilization |
| 132 | + return abs(epi_without_sha - epi_with_sha) < tolerance |
| 133 | + |
| 134 | + |
| 135 | +def validate_idempotence( |
| 136 | + G: TNFRGraph, |
| 137 | + node: NodeId, |
| 138 | + tolerance: float = 0.05, |
| 139 | +) -> bool: |
| 140 | + """Validate that SHA is idempotent: SHA^n = SHA. |
| 141 | + |
| 142 | + Tests the algebraic property: SHA(SHA(ω)) ≈ SHA(ω) |
| 143 | + |
| 144 | + Physical basis: Once νf ≈ 0 after first SHA, subsequent applications |
| 145 | + cannot reduce it further. The effect is saturated. |
| 146 | + |
| 147 | + Due to grammar constraints against consecutive SHA operators, we test |
| 148 | + idempotence by comparing SHA behavior in different sequence contexts. |
| 149 | + The key property: SHA always has the same characteristic effect |
| 150 | + (reduce νf to minimum, preserve EPI). |
| 151 | + |
| 152 | + Parameters |
| 153 | + ---------- |
| 154 | + G : TNFRGraph |
| 155 | + Graph containing the node to validate |
| 156 | + node : NodeId |
| 157 | + Target node identifier |
| 158 | + tolerance : float, optional |
| 159 | + Numerical tolerance for νf comparison (default: 0.05) |
| 160 | + |
| 161 | + Returns |
| 162 | + ------- |
| 163 | + bool |
| 164 | + True if idempotence holds (consistent SHA behavior) |
| 165 | + |
| 166 | + Notes |
| 167 | + ----- |
| 168 | + Tests SHA in two different contexts: |
| 169 | + - Context 1: Emission → Coherence → Silence |
| 170 | + - Context 2: Emission → Coherence → Resonance → Silence |
| 171 | + |
| 172 | + In both cases, SHA should reduce νf to near-zero and preserve EPI. |
| 173 | + This validates idempotent behavior: SHA effect is consistent and saturated. |
| 174 | + |
| 175 | + Examples |
| 176 | + -------- |
| 177 | + >>> from tnfr.structural import create_nfr |
| 178 | + >>> from tnfr.operators.algebra import validate_idempotence |
| 179 | + >>> G, node = create_nfr("test", epi=0.65, vf=1.30) |
| 180 | + >>> validate_idempotence(G, node) # doctest: +SKIP |
| 181 | + True |
| 182 | + """ |
| 183 | + from ..alias import get_attr |
| 184 | + from ..constants.aliases import ALIAS_VF |
| 185 | + from .definitions import Silence, Emission, Coherence, Resonance |
| 186 | + from ..structural import run_sequence |
| 187 | + |
| 188 | + # Test 1: SHA after simple sequence |
| 189 | + G1 = G.copy() |
| 190 | + run_sequence(G1, node, [Emission(), Coherence(), Silence()]) |
| 191 | + vf_context1 = float(get_attr(G1.nodes[node], ALIAS_VF, 0.0)) |
| 192 | + |
| 193 | + # Test 2: SHA after longer sequence (with Resonance added) |
| 194 | + G2 = G.copy() |
| 195 | + run_sequence(G2, node, [Emission(), Coherence(), Resonance(), Silence()]) |
| 196 | + vf_context2 = float(get_attr(G2.nodes[node], ALIAS_VF, 0.0)) |
| 197 | + |
| 198 | + # Idempotence property: SHA behavior is consistent |
| 199 | + # Both νf values should be near-zero (SHA's characteristic effect) |
| 200 | + vf_threshold = 0.15 # SHA should reduce νf below this |
| 201 | + both_minimal = (vf_context1 < vf_threshold) and (vf_context2 < vf_threshold) |
| 202 | + |
| 203 | + # Both should be similar (consistent behavior) |
| 204 | + consistent = abs(vf_context1 - vf_context2) < tolerance |
| 205 | + |
| 206 | + return both_minimal and consistent |
| 207 | + |
| 208 | + |
| 209 | +def validate_commutativity_nul( |
| 210 | + G: TNFRGraph, |
| 211 | + node: NodeId, |
| 212 | + tolerance: float = 0.02, |
| 213 | +) -> bool: |
| 214 | + """Validate that SHA and NUL commute: SHA(NUL(ω)) ≈ NUL(SHA(ω)). |
| 215 | + |
| 216 | + Tests the algebraic property that Silence and Contraction can be applied |
| 217 | + in either order with equivalent results. |
| 218 | + |
| 219 | + Physical basis: SHA and NUL reduce orthogonal dimensions of state space: |
| 220 | + - SHA reduces νf (reorganization capacity) |
| 221 | + - NUL reduces EPI complexity (structural dimensionality) |
| 222 | + |
| 223 | + Since they act on independent dimensions, order doesn't matter for |
| 224 | + final state. |
| 225 | + |
| 226 | + Parameters |
| 227 | + ---------- |
| 228 | + G : TNFRGraph |
| 229 | + Graph containing the node to validate |
| 230 | + node : NodeId |
| 231 | + Target node identifier |
| 232 | + tolerance : float, optional |
| 233 | + Numerical tolerance for EPI and νf comparison (default: 0.02) |
| 234 | + |
| 235 | + Returns |
| 236 | + ------- |
| 237 | + bool |
| 238 | + True if commutativity holds within tolerance |
| 239 | + |
| 240 | + Notes |
| 241 | + ----- |
| 242 | + Tests two paths (both grammar-valid, using Transition as generator): |
| 243 | + 1. Transition → Silence → Contraction |
| 244 | + 2. Transition → Contraction → Silence |
| 245 | + |
| 246 | + The property holds if both paths result in equivalent EPI and νf values. |
| 247 | + |
| 248 | + Examples |
| 249 | + -------- |
| 250 | + >>> from tnfr.structural import create_nfr |
| 251 | + >>> from tnfr.operators.algebra import validate_commutativity_nul |
| 252 | + >>> G, node = create_nfr("test", epi=0.55, vf=1.10) |
| 253 | + >>> validate_commutativity_nul(G, node) # doctest: +SKIP |
| 254 | + True |
| 255 | + """ |
| 256 | + from ..alias import get_attr |
| 257 | + from ..constants.aliases import ALIAS_EPI, ALIAS_VF |
| 258 | + from .definitions import Silence, Contraction, Transition |
| 259 | + from ..structural import run_sequence |
| 260 | + |
| 261 | + # Path 1: NAV → SHA → NUL (Transition then Silence then Contraction) |
| 262 | + G1 = G.copy() |
| 263 | + run_sequence(G1, node, [Transition(), Silence(), Contraction()]) |
| 264 | + epi_sha_nul = float(get_attr(G1.nodes[node], ALIAS_EPI, 0.0)) |
| 265 | + vf_sha_nul = float(get_attr(G1.nodes[node], ALIAS_VF, 0.0)) |
| 266 | + |
| 267 | + # Path 2: NAV → NUL → SHA (Transition then Contraction then Silence) |
| 268 | + G2 = G.copy() |
| 269 | + run_sequence(G2, node, [Transition(), Contraction(), Silence()]) |
| 270 | + epi_nul_sha = float(get_attr(G2.nodes[node], ALIAS_EPI, 0.0)) |
| 271 | + vf_nul_sha = float(get_attr(G2.nodes[node], ALIAS_VF, 0.0)) |
| 272 | + |
| 273 | + # Validate commutativity: both paths should produce similar results |
| 274 | + epi_commutes = abs(epi_sha_nul - epi_nul_sha) < tolerance |
| 275 | + vf_commutes = abs(vf_sha_nul - vf_nul_sha) < tolerance |
| 276 | + |
| 277 | + return epi_commutes and vf_commutes |
0 commit comments