|
1 | | -"""Canonical grammar and sequence validation for structural operators. |
| 1 | +"""TNFR Operator Grammar (Compatibility Layer). |
| 2 | +
|
| 3 | +This module maintains backward compatibility with the old C1-C3 grammar system. |
| 4 | +All validation now delegates to the unified U1-U4 grammar in unified_grammar.py. |
| 5 | +
|
| 6 | +**MIGRATION NOTE:** |
| 7 | +New code should import directly from unified_grammar.py: |
| 8 | +
|
| 9 | + from tnfr.operators.unified_grammar import UnifiedGrammarValidator, validate_unified |
| 10 | +
|
| 11 | +See UNIFIED_GRAMMAR_RULES.md for complete migration guide. |
| 12 | +
|
| 13 | +Old Grammar (C1-C3) → Unified Grammar (U1-U4) |
| 14 | +----------------------------------------------- |
| 15 | +C1: EXISTENCE & CLOSURE → U1: STRUCTURAL INITIATION & CLOSURE |
| 16 | +C2: BOUNDEDNESS → U2: CONVERGENCE & BOUNDEDNESS |
| 17 | +C3: THRESHOLD PHYSICS → U4: BIFURCATION DYNAMICS |
2 | 18 |
|
3 | 19 | This module enforces TNFR canonical constraints that emerge naturally from |
4 | 20 | the fundamental physics of the nodal equation: |
|
241 | 257 | from ..utils import get_logger |
242 | 258 | from .registry import OPERATORS |
243 | 259 |
|
| 260 | +# Import unified grammar - single source of truth for U1-U4 constraints |
| 261 | +from .unified_grammar import ( |
| 262 | + UnifiedGrammarValidator, |
| 263 | + validate_unified, |
| 264 | + GENERATORS as UNIFIED_GENERATORS, |
| 265 | + CLOSURES as UNIFIED_CLOSURES, |
| 266 | + STABILIZERS as UNIFIED_STABILIZERS, |
| 267 | + DESTABILIZERS as UNIFIED_DESTABILIZERS, |
| 268 | + COUPLING_RESONANCE as UNIFIED_COUPLING_RESONANCE, |
| 269 | + BIFURCATION_TRIGGERS as UNIFIED_BIFURCATION_TRIGGERS, |
| 270 | + BIFURCATION_HANDLERS as UNIFIED_BIFURCATION_HANDLERS, |
| 271 | + TRANSFORMERS as UNIFIED_TRANSFORMERS, |
| 272 | +) |
| 273 | + |
244 | 274 | try: # pragma: no cover - optional dependency import |
245 | 275 | from jsonschema import Draft7Validator |
246 | 276 | from jsonschema import exceptions as _jsonschema_exceptions |
|
285 | 315 | "recognize_coherence_sequences", |
286 | 316 | "optimize_coherence_sequence", |
287 | 317 | "suggest_coherence_sequence", |
| 318 | + # Deprecated C1-C3 validators (for backward compatibility) |
| 319 | + "validate_c1_existence", |
| 320 | + "validate_c2_boundedness", |
| 321 | + "validate_c3_threshold", |
| 322 | + # Re-export unified grammar (single source of truth) |
| 323 | + "UnifiedGrammarValidator", |
| 324 | + "validate_unified", |
| 325 | + # Re-export unified operator sets |
| 326 | + "UNIFIED_GENERATORS", |
| 327 | + "UNIFIED_CLOSURES", |
| 328 | + "UNIFIED_STABILIZERS", |
| 329 | + "UNIFIED_DESTABILIZERS", |
| 330 | + "UNIFIED_COUPLING_RESONANCE", |
| 331 | + "UNIFIED_BIFURCATION_TRIGGERS", |
| 332 | + "UNIFIED_BIFURCATION_HANDLERS", |
| 333 | + "UNIFIED_TRANSFORMERS", |
288 | 334 | ] |
289 | 335 |
|
290 | 336 | logger = get_logger(__name__) |
|
321 | 367 | } |
322 | 368 |
|
323 | 369 |
|
| 370 | +# ============================================================================ |
| 371 | +# Deprecation Warning Helper |
| 372 | +# ============================================================================ |
| 373 | + |
| 374 | +def _emit_c1_c3_deprecation_warning(old_function: str, new_function: str) -> None: |
| 375 | + """Emit deprecation warning for old C1-C3 grammar functions. |
| 376 | + |
| 377 | + Parameters |
| 378 | + ---------- |
| 379 | + old_function : str |
| 380 | + Name of the deprecated function |
| 381 | + new_function : str |
| 382 | + Name of the replacement function in unified_grammar |
| 383 | + """ |
| 384 | + warnings.warn( |
| 385 | + f"{old_function} is deprecated. Use UnifiedGrammarValidator.{new_function}(). " |
| 386 | + "See UNIFIED_GRAMMAR_RULES.md for migration guide.", |
| 387 | + DeprecationWarning, |
| 388 | + stacklevel=3 |
| 389 | + ) |
| 390 | + |
| 391 | + |
324 | 392 | def glyph_function_name( |
325 | 393 | val: Glyph | str | None, *, default: str | None = None |
326 | 394 | ) -> str | None: |
@@ -2127,9 +2195,171 @@ def _analyse_sequence(names: Iterable[str]) -> SequenceValidationResult: |
2127 | 2195 | ) |
2128 | 2196 |
|
2129 | 2197 |
|
| 2198 | +# ============================================================================ |
| 2199 | +# Deprecated C1-C3 Validation Functions (Backward Compatibility) |
| 2200 | +# ============================================================================ |
| 2201 | + |
| 2202 | +def validate_c1_existence(sequence: list[str]) -> bool: |
| 2203 | + """DEPRECATED: Use UnifiedGrammarValidator.validate_initiation() and validate_closure(). |
| 2204 | + |
| 2205 | + This function implements the old C1 constraint (EXISTENCE & CLOSURE). |
| 2206 | + Please migrate to unified grammar: |
| 2207 | + - See: src/tnfr/operators/unified_grammar.py |
| 2208 | + - Docs: UNIFIED_GRAMMAR_RULES.md |
| 2209 | + |
| 2210 | + Will be removed in version 8.0.0. |
| 2211 | + |
| 2212 | + Parameters |
| 2213 | + ---------- |
| 2214 | + sequence : list[str] |
| 2215 | + Sequence of operator names to validate |
| 2216 | + |
| 2217 | + Returns |
| 2218 | + ------- |
| 2219 | + bool |
| 2220 | + True if sequence has valid start and end operators |
| 2221 | + """ |
| 2222 | + _emit_c1_c3_deprecation_warning("validate_c1_existence", "validate_initiation and validate_closure") |
| 2223 | + |
| 2224 | + # For backward compatibility, we check the old C1 rules |
| 2225 | + # which map to U1a (initiation) and U1b (closure) |
| 2226 | + if not sequence: |
| 2227 | + return False |
| 2228 | + |
| 2229 | + # Check start (should be generator) |
| 2230 | + first = sequence[0] |
| 2231 | + if first not in VALID_START_OPERATORS: |
| 2232 | + return False |
| 2233 | + |
| 2234 | + # Check end (should be closure) |
| 2235 | + last = sequence[-1] |
| 2236 | + if last not in VALID_END_OPERATORS: |
| 2237 | + return False |
| 2238 | + |
| 2239 | + return True |
| 2240 | + |
| 2241 | + |
| 2242 | +def validate_c2_boundedness(sequence: list[str]) -> bool: |
| 2243 | + """DEPRECATED: Use UnifiedGrammarValidator.validate_convergence(). |
| 2244 | + |
| 2245 | + This function implements the old C2 constraint (BOUNDEDNESS). |
| 2246 | + Please migrate to unified grammar: |
| 2247 | + - See: src/tnfr/operators/unified_grammar.py |
| 2248 | + - Docs: UNIFIED_GRAMMAR_RULES.md |
| 2249 | + |
| 2250 | + Will be removed in version 8.0.0. |
| 2251 | + |
| 2252 | + Parameters |
| 2253 | + ---------- |
| 2254 | + sequence : list[str] |
| 2255 | + Sequence of operator names to validate |
| 2256 | + |
| 2257 | + Returns |
| 2258 | + ------- |
| 2259 | + bool |
| 2260 | + True if destabilizers are balanced by stabilizers |
| 2261 | + """ |
| 2262 | + _emit_c1_c3_deprecation_warning("validate_c2_boundedness", "validate_convergence") |
| 2263 | + |
| 2264 | + # Check if sequence has destabilizers |
| 2265 | + has_destabilizers = any(op in DESTABILIZERS for op in sequence) |
| 2266 | + |
| 2267 | + if not has_destabilizers: |
| 2268 | + return True # No destabilizers = no divergence risk |
| 2269 | + |
| 2270 | + # Check for stabilizers (IL or THOL) |
| 2271 | + has_stabilizers = any(op in {COHERENCE, SELF_ORGANIZATION} for op in sequence) |
| 2272 | + |
| 2273 | + return has_stabilizers |
| 2274 | + |
| 2275 | + |
| 2276 | +def validate_c3_threshold(sequence: list[str]) -> bool: |
| 2277 | + """DEPRECATED: Use UnifiedGrammarValidator.validate_bifurcation_dynamics(). |
| 2278 | + |
| 2279 | + This function implements the old C3 constraint (THRESHOLD PHYSICS). |
| 2280 | + Please migrate to unified grammar: |
| 2281 | + - See: src/tnfr/operators/unified_grammar.py |
| 2282 | + - Docs: UNIFIED_GRAMMAR_RULES.md |
| 2283 | + |
| 2284 | + Will be removed in version 8.0.0. |
| 2285 | + |
| 2286 | + Parameters |
| 2287 | + ---------- |
| 2288 | + sequence : list[str] |
| 2289 | + Sequence of operator names to validate |
| 2290 | + |
| 2291 | + Returns |
| 2292 | + ------- |
| 2293 | + bool |
| 2294 | + True if bifurcation triggers have appropriate handlers |
| 2295 | + """ |
| 2296 | + _emit_c1_c3_deprecation_warning("validate_c3_threshold", "validate_bifurcation_dynamics") |
| 2297 | + |
| 2298 | + # Check if transformers (ZHIR/THOL) are preceded by destabilizers |
| 2299 | + for i, op in enumerate(sequence): |
| 2300 | + if op in TRANSFORMERS: |
| 2301 | + # Look back for recent destabilizer (within bifurcation window) |
| 2302 | + window_start = max(0, i - BIFURCATION_WINDOW) |
| 2303 | + recent_ops = sequence[window_start:i] |
| 2304 | + |
| 2305 | + has_recent_destabilizer = any( |
| 2306 | + op in DESTABILIZERS for op in recent_ops |
| 2307 | + ) |
| 2308 | + |
| 2309 | + if not has_recent_destabilizer: |
| 2310 | + return False |
| 2311 | + |
| 2312 | + # For ZHIR specifically, also check for recent IL |
| 2313 | + if op == MUTATION: |
| 2314 | + has_recent_coherence = COHERENCE in recent_ops |
| 2315 | + if not has_recent_coherence: |
| 2316 | + return False |
| 2317 | + |
| 2318 | + return True |
| 2319 | + |
| 2320 | + |
2130 | 2321 | def validate_sequence( |
2131 | 2322 | names: Iterable[str] | object = _MISSING, **kwargs: object |
2132 | 2323 | ) -> ValidationOutcome[tuple[str, ...]]: |
| 2324 | + """Validate operator sequence using TNFR grammar constraints. |
| 2325 | + |
| 2326 | + This function validates sequences using the canonical C1-C3 constraints |
| 2327 | + that are now unified in U1-U4 (see unified_grammar.py). |
| 2328 | + |
| 2329 | + Parameters |
| 2330 | + ---------- |
| 2331 | + names : Iterable[str] |
| 2332 | + Sequence of operator names to validate |
| 2333 | + |
| 2334 | + Returns |
| 2335 | + ------- |
| 2336 | + ValidationOutcome[tuple[str, ...]] |
| 2337 | + Validation result with pass/fail status and detailed messages |
| 2338 | + |
| 2339 | + Notes |
| 2340 | + ----- |
| 2341 | + This function maintains the original grammar.py validation behavior |
| 2342 | + while conceptually aligning with the unified U1-U4 constraints: |
| 2343 | + |
| 2344 | + - C1 (EXISTENCE & CLOSURE) → U1 (STRUCTURAL INITIATION & CLOSURE) |
| 2345 | + - C2 (BOUNDEDNESS) → U2 (CONVERGENCE & BOUNDEDNESS) |
| 2346 | + - C3 (THRESHOLD PHYSICS) → U4 (BIFURCATION DYNAMICS) |
| 2347 | + |
| 2348 | + For new code, consider using UnifiedGrammarValidator directly: |
| 2349 | + |
| 2350 | + from tnfr.operators.unified_grammar import UnifiedGrammarValidator |
| 2351 | + valid, msg = UnifiedGrammarValidator.validate(ops) |
| 2352 | + |
| 2353 | + See Also |
| 2354 | + -------- |
| 2355 | + UnifiedGrammarValidator : Single source of truth for U1-U4 constraints |
| 2356 | + validate_unified : Convenience function for unified validation |
| 2357 | + |
| 2358 | + References |
| 2359 | + ---------- |
| 2360 | + - UNIFIED_GRAMMAR_RULES.md: Complete physics derivations |
| 2361 | + - unified_grammar.py: Canonical U1-U4 implementation |
| 2362 | + """ |
2133 | 2363 | if kwargs: |
2134 | 2364 | unexpected = ", ".join(sorted(kwargs)) |
2135 | 2365 | raise TypeError( |
|
0 commit comments