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.

Files changed (360) hide show
  1. tnfr/__init__.py +375 -56
  2. tnfr/__init__.pyi +33 -0
  3. tnfr/_compat.py +10 -0
  4. tnfr/_generated_version.py +34 -0
  5. tnfr/_version.py +49 -0
  6. tnfr/_version.pyi +7 -0
  7. tnfr/alias.py +723 -0
  8. tnfr/alias.pyi +108 -0
  9. tnfr/backends/__init__.py +354 -0
  10. tnfr/backends/jax_backend.py +173 -0
  11. tnfr/backends/numpy_backend.py +238 -0
  12. tnfr/backends/optimized_numpy.py +420 -0
  13. tnfr/backends/torch_backend.py +408 -0
  14. tnfr/cache.py +171 -0
  15. tnfr/cache.pyi +13 -0
  16. tnfr/cli/__init__.py +110 -0
  17. tnfr/cli/__init__.pyi +26 -0
  18. tnfr/cli/arguments.py +489 -0
  19. tnfr/cli/arguments.pyi +29 -0
  20. tnfr/cli/execution.py +914 -0
  21. tnfr/cli/execution.pyi +70 -0
  22. tnfr/cli/interactive_validator.py +614 -0
  23. tnfr/cli/utils.py +51 -0
  24. tnfr/cli/utils.pyi +7 -0
  25. tnfr/cli/validate.py +236 -0
  26. tnfr/compat/__init__.py +85 -0
  27. tnfr/compat/dataclass.py +136 -0
  28. tnfr/compat/jsonschema_stub.py +61 -0
  29. tnfr/compat/matplotlib_stub.py +73 -0
  30. tnfr/compat/numpy_stub.py +155 -0
  31. tnfr/config/__init__.py +224 -0
  32. tnfr/config/__init__.pyi +10 -0
  33. tnfr/config/constants.py +104 -0
  34. tnfr/config/constants.pyi +12 -0
  35. tnfr/config/defaults.py +54 -0
  36. tnfr/config/defaults_core.py +212 -0
  37. tnfr/config/defaults_init.py +33 -0
  38. tnfr/config/defaults_metric.py +104 -0
  39. tnfr/config/feature_flags.py +81 -0
  40. tnfr/config/feature_flags.pyi +16 -0
  41. tnfr/config/glyph_constants.py +31 -0
  42. tnfr/config/init.py +77 -0
  43. tnfr/config/init.pyi +8 -0
  44. tnfr/config/operator_names.py +254 -0
  45. tnfr/config/operator_names.pyi +36 -0
  46. tnfr/config/physics_derivation.py +354 -0
  47. tnfr/config/presets.py +83 -0
  48. tnfr/config/presets.pyi +7 -0
  49. tnfr/config/security.py +927 -0
  50. tnfr/config/thresholds.py +114 -0
  51. tnfr/config/tnfr_config.py +498 -0
  52. tnfr/constants/__init__.py +92 -0
  53. tnfr/constants/__init__.pyi +92 -0
  54. tnfr/constants/aliases.py +33 -0
  55. tnfr/constants/aliases.pyi +27 -0
  56. tnfr/constants/init.py +33 -0
  57. tnfr/constants/init.pyi +12 -0
  58. tnfr/constants/metric.py +104 -0
  59. tnfr/constants/metric.pyi +19 -0
  60. tnfr/core/__init__.py +33 -0
  61. tnfr/core/container.py +226 -0
  62. tnfr/core/default_implementations.py +329 -0
  63. tnfr/core/interfaces.py +279 -0
  64. tnfr/dynamics/__init__.py +238 -0
  65. tnfr/dynamics/__init__.pyi +83 -0
  66. tnfr/dynamics/adaptation.py +267 -0
  67. tnfr/dynamics/adaptation.pyi +7 -0
  68. tnfr/dynamics/adaptive_sequences.py +189 -0
  69. tnfr/dynamics/adaptive_sequences.pyi +14 -0
  70. tnfr/dynamics/aliases.py +23 -0
  71. tnfr/dynamics/aliases.pyi +19 -0
  72. tnfr/dynamics/bifurcation.py +232 -0
  73. tnfr/dynamics/canonical.py +229 -0
  74. tnfr/dynamics/canonical.pyi +48 -0
  75. tnfr/dynamics/coordination.py +385 -0
  76. tnfr/dynamics/coordination.pyi +25 -0
  77. tnfr/dynamics/dnfr.py +3034 -0
  78. tnfr/dynamics/dnfr.pyi +26 -0
  79. tnfr/dynamics/dynamic_limits.py +225 -0
  80. tnfr/dynamics/feedback.py +252 -0
  81. tnfr/dynamics/feedback.pyi +24 -0
  82. tnfr/dynamics/fused_dnfr.py +454 -0
  83. tnfr/dynamics/homeostasis.py +157 -0
  84. tnfr/dynamics/homeostasis.pyi +14 -0
  85. tnfr/dynamics/integrators.py +661 -0
  86. tnfr/dynamics/integrators.pyi +36 -0
  87. tnfr/dynamics/learning.py +310 -0
  88. tnfr/dynamics/learning.pyi +33 -0
  89. tnfr/dynamics/metabolism.py +254 -0
  90. tnfr/dynamics/nbody.py +796 -0
  91. tnfr/dynamics/nbody_tnfr.py +783 -0
  92. tnfr/dynamics/propagation.py +326 -0
  93. tnfr/dynamics/runtime.py +908 -0
  94. tnfr/dynamics/runtime.pyi +77 -0
  95. tnfr/dynamics/sampling.py +36 -0
  96. tnfr/dynamics/sampling.pyi +7 -0
  97. tnfr/dynamics/selectors.py +711 -0
  98. tnfr/dynamics/selectors.pyi +85 -0
  99. tnfr/dynamics/structural_clip.py +207 -0
  100. tnfr/errors/__init__.py +37 -0
  101. tnfr/errors/contextual.py +492 -0
  102. tnfr/execution.py +223 -0
  103. tnfr/execution.pyi +45 -0
  104. tnfr/extensions/__init__.py +205 -0
  105. tnfr/extensions/__init__.pyi +18 -0
  106. tnfr/extensions/base.py +173 -0
  107. tnfr/extensions/base.pyi +35 -0
  108. tnfr/extensions/business/__init__.py +71 -0
  109. tnfr/extensions/business/__init__.pyi +11 -0
  110. tnfr/extensions/business/cookbook.py +88 -0
  111. tnfr/extensions/business/cookbook.pyi +8 -0
  112. tnfr/extensions/business/health_analyzers.py +202 -0
  113. tnfr/extensions/business/health_analyzers.pyi +9 -0
  114. tnfr/extensions/business/patterns.py +183 -0
  115. tnfr/extensions/business/patterns.pyi +8 -0
  116. tnfr/extensions/medical/__init__.py +73 -0
  117. tnfr/extensions/medical/__init__.pyi +11 -0
  118. tnfr/extensions/medical/cookbook.py +88 -0
  119. tnfr/extensions/medical/cookbook.pyi +8 -0
  120. tnfr/extensions/medical/health_analyzers.py +181 -0
  121. tnfr/extensions/medical/health_analyzers.pyi +9 -0
  122. tnfr/extensions/medical/patterns.py +163 -0
  123. tnfr/extensions/medical/patterns.pyi +8 -0
  124. tnfr/flatten.py +262 -0
  125. tnfr/flatten.pyi +21 -0
  126. tnfr/gamma.py +354 -0
  127. tnfr/gamma.pyi +36 -0
  128. tnfr/glyph_history.py +377 -0
  129. tnfr/glyph_history.pyi +35 -0
  130. tnfr/glyph_runtime.py +19 -0
  131. tnfr/glyph_runtime.pyi +8 -0
  132. tnfr/immutable.py +218 -0
  133. tnfr/immutable.pyi +36 -0
  134. tnfr/initialization.py +203 -0
  135. tnfr/initialization.pyi +65 -0
  136. tnfr/io.py +10 -0
  137. tnfr/io.pyi +13 -0
  138. tnfr/locking.py +37 -0
  139. tnfr/locking.pyi +7 -0
  140. tnfr/mathematics/__init__.py +79 -0
  141. tnfr/mathematics/backend.py +453 -0
  142. tnfr/mathematics/backend.pyi +99 -0
  143. tnfr/mathematics/dynamics.py +408 -0
  144. tnfr/mathematics/dynamics.pyi +90 -0
  145. tnfr/mathematics/epi.py +391 -0
  146. tnfr/mathematics/epi.pyi +65 -0
  147. tnfr/mathematics/generators.py +242 -0
  148. tnfr/mathematics/generators.pyi +29 -0
  149. tnfr/mathematics/metrics.py +119 -0
  150. tnfr/mathematics/metrics.pyi +16 -0
  151. tnfr/mathematics/operators.py +239 -0
  152. tnfr/mathematics/operators.pyi +59 -0
  153. tnfr/mathematics/operators_factory.py +124 -0
  154. tnfr/mathematics/operators_factory.pyi +11 -0
  155. tnfr/mathematics/projection.py +87 -0
  156. tnfr/mathematics/projection.pyi +33 -0
  157. tnfr/mathematics/runtime.py +182 -0
  158. tnfr/mathematics/runtime.pyi +64 -0
  159. tnfr/mathematics/spaces.py +256 -0
  160. tnfr/mathematics/spaces.pyi +83 -0
  161. tnfr/mathematics/transforms.py +305 -0
  162. tnfr/mathematics/transforms.pyi +62 -0
  163. tnfr/metrics/__init__.py +79 -0
  164. tnfr/metrics/__init__.pyi +20 -0
  165. tnfr/metrics/buffer_cache.py +163 -0
  166. tnfr/metrics/buffer_cache.pyi +24 -0
  167. tnfr/metrics/cache_utils.py +214 -0
  168. tnfr/metrics/coherence.py +2009 -0
  169. tnfr/metrics/coherence.pyi +129 -0
  170. tnfr/metrics/common.py +158 -0
  171. tnfr/metrics/common.pyi +35 -0
  172. tnfr/metrics/core.py +316 -0
  173. tnfr/metrics/core.pyi +13 -0
  174. tnfr/metrics/diagnosis.py +833 -0
  175. tnfr/metrics/diagnosis.pyi +86 -0
  176. tnfr/metrics/emergence.py +245 -0
  177. tnfr/metrics/export.py +179 -0
  178. tnfr/metrics/export.pyi +7 -0
  179. tnfr/metrics/glyph_timing.py +379 -0
  180. tnfr/metrics/glyph_timing.pyi +81 -0
  181. tnfr/metrics/learning_metrics.py +280 -0
  182. tnfr/metrics/learning_metrics.pyi +21 -0
  183. tnfr/metrics/phase_coherence.py +351 -0
  184. tnfr/metrics/phase_compatibility.py +349 -0
  185. tnfr/metrics/reporting.py +183 -0
  186. tnfr/metrics/reporting.pyi +25 -0
  187. tnfr/metrics/sense_index.py +1203 -0
  188. tnfr/metrics/sense_index.pyi +9 -0
  189. tnfr/metrics/trig.py +373 -0
  190. tnfr/metrics/trig.pyi +13 -0
  191. tnfr/metrics/trig_cache.py +233 -0
  192. tnfr/metrics/trig_cache.pyi +10 -0
  193. tnfr/multiscale/__init__.py +32 -0
  194. tnfr/multiscale/hierarchical.py +517 -0
  195. tnfr/node.py +763 -0
  196. tnfr/node.pyi +139 -0
  197. tnfr/observers.py +255 -130
  198. tnfr/observers.pyi +31 -0
  199. tnfr/ontosim.py +144 -137
  200. tnfr/ontosim.pyi +28 -0
  201. tnfr/operators/__init__.py +1672 -0
  202. tnfr/operators/__init__.pyi +31 -0
  203. tnfr/operators/algebra.py +277 -0
  204. tnfr/operators/canonical_patterns.py +420 -0
  205. tnfr/operators/cascade.py +267 -0
  206. tnfr/operators/cycle_detection.py +358 -0
  207. tnfr/operators/definitions.py +4108 -0
  208. tnfr/operators/definitions.pyi +78 -0
  209. tnfr/operators/grammar.py +1164 -0
  210. tnfr/operators/grammar.pyi +140 -0
  211. tnfr/operators/hamiltonian.py +710 -0
  212. tnfr/operators/health_analyzer.py +809 -0
  213. tnfr/operators/jitter.py +272 -0
  214. tnfr/operators/jitter.pyi +11 -0
  215. tnfr/operators/lifecycle.py +314 -0
  216. tnfr/operators/metabolism.py +618 -0
  217. tnfr/operators/metrics.py +2138 -0
  218. tnfr/operators/network_analysis/__init__.py +27 -0
  219. tnfr/operators/network_analysis/source_detection.py +186 -0
  220. tnfr/operators/nodal_equation.py +395 -0
  221. tnfr/operators/pattern_detection.py +660 -0
  222. tnfr/operators/patterns.py +669 -0
  223. tnfr/operators/postconditions/__init__.py +38 -0
  224. tnfr/operators/postconditions/mutation.py +236 -0
  225. tnfr/operators/preconditions/__init__.py +1226 -0
  226. tnfr/operators/preconditions/coherence.py +305 -0
  227. tnfr/operators/preconditions/dissonance.py +236 -0
  228. tnfr/operators/preconditions/emission.py +128 -0
  229. tnfr/operators/preconditions/mutation.py +580 -0
  230. tnfr/operators/preconditions/reception.py +125 -0
  231. tnfr/operators/preconditions/resonance.py +364 -0
  232. tnfr/operators/registry.py +74 -0
  233. tnfr/operators/registry.pyi +9 -0
  234. tnfr/operators/remesh.py +1809 -0
  235. tnfr/operators/remesh.pyi +26 -0
  236. tnfr/operators/structural_units.py +268 -0
  237. tnfr/operators/unified_grammar.py +105 -0
  238. tnfr/parallel/__init__.py +54 -0
  239. tnfr/parallel/auto_scaler.py +234 -0
  240. tnfr/parallel/distributed.py +384 -0
  241. tnfr/parallel/engine.py +238 -0
  242. tnfr/parallel/gpu_engine.py +420 -0
  243. tnfr/parallel/monitoring.py +248 -0
  244. tnfr/parallel/partitioner.py +459 -0
  245. tnfr/py.typed +0 -0
  246. tnfr/recipes/__init__.py +22 -0
  247. tnfr/recipes/cookbook.py +743 -0
  248. tnfr/rng.py +178 -0
  249. tnfr/rng.pyi +26 -0
  250. tnfr/schemas/__init__.py +8 -0
  251. tnfr/schemas/grammar.json +94 -0
  252. tnfr/sdk/__init__.py +107 -0
  253. tnfr/sdk/__init__.pyi +19 -0
  254. tnfr/sdk/adaptive_system.py +173 -0
  255. tnfr/sdk/adaptive_system.pyi +21 -0
  256. tnfr/sdk/builders.py +370 -0
  257. tnfr/sdk/builders.pyi +51 -0
  258. tnfr/sdk/fluent.py +1121 -0
  259. tnfr/sdk/fluent.pyi +74 -0
  260. tnfr/sdk/templates.py +342 -0
  261. tnfr/sdk/templates.pyi +41 -0
  262. tnfr/sdk/utils.py +341 -0
  263. tnfr/secure_config.py +46 -0
  264. tnfr/security/__init__.py +70 -0
  265. tnfr/security/database.py +514 -0
  266. tnfr/security/subprocess.py +503 -0
  267. tnfr/security/validation.py +290 -0
  268. tnfr/selector.py +247 -0
  269. tnfr/selector.pyi +19 -0
  270. tnfr/sense.py +378 -0
  271. tnfr/sense.pyi +23 -0
  272. tnfr/services/__init__.py +17 -0
  273. tnfr/services/orchestrator.py +325 -0
  274. tnfr/sparse/__init__.py +39 -0
  275. tnfr/sparse/representations.py +492 -0
  276. tnfr/structural.py +705 -0
  277. tnfr/structural.pyi +83 -0
  278. tnfr/telemetry/__init__.py +35 -0
  279. tnfr/telemetry/cache_metrics.py +226 -0
  280. tnfr/telemetry/cache_metrics.pyi +64 -0
  281. tnfr/telemetry/nu_f.py +422 -0
  282. tnfr/telemetry/nu_f.pyi +108 -0
  283. tnfr/telemetry/verbosity.py +36 -0
  284. tnfr/telemetry/verbosity.pyi +15 -0
  285. tnfr/tokens.py +58 -0
  286. tnfr/tokens.pyi +36 -0
  287. tnfr/tools/__init__.py +20 -0
  288. tnfr/tools/domain_templates.py +478 -0
  289. tnfr/tools/sequence_generator.py +846 -0
  290. tnfr/topology/__init__.py +13 -0
  291. tnfr/topology/asymmetry.py +151 -0
  292. tnfr/trace.py +543 -0
  293. tnfr/trace.pyi +42 -0
  294. tnfr/tutorials/__init__.py +38 -0
  295. tnfr/tutorials/autonomous_evolution.py +285 -0
  296. tnfr/tutorials/interactive.py +1576 -0
  297. tnfr/tutorials/structural_metabolism.py +238 -0
  298. tnfr/types.py +775 -0
  299. tnfr/types.pyi +357 -0
  300. tnfr/units.py +68 -0
  301. tnfr/units.pyi +13 -0
  302. tnfr/utils/__init__.py +282 -0
  303. tnfr/utils/__init__.pyi +215 -0
  304. tnfr/utils/cache.py +4223 -0
  305. tnfr/utils/cache.pyi +470 -0
  306. tnfr/utils/callbacks.py +375 -0
  307. tnfr/utils/callbacks.pyi +49 -0
  308. tnfr/utils/chunks.py +108 -0
  309. tnfr/utils/chunks.pyi +22 -0
  310. tnfr/utils/data.py +428 -0
  311. tnfr/utils/data.pyi +74 -0
  312. tnfr/utils/graph.py +85 -0
  313. tnfr/utils/graph.pyi +10 -0
  314. tnfr/utils/init.py +821 -0
  315. tnfr/utils/init.pyi +80 -0
  316. tnfr/utils/io.py +559 -0
  317. tnfr/utils/io.pyi +66 -0
  318. tnfr/utils/numeric.py +114 -0
  319. tnfr/utils/numeric.pyi +21 -0
  320. tnfr/validation/__init__.py +257 -0
  321. tnfr/validation/__init__.pyi +85 -0
  322. tnfr/validation/compatibility.py +460 -0
  323. tnfr/validation/compatibility.pyi +6 -0
  324. tnfr/validation/config.py +73 -0
  325. tnfr/validation/graph.py +139 -0
  326. tnfr/validation/graph.pyi +18 -0
  327. tnfr/validation/input_validation.py +755 -0
  328. tnfr/validation/invariants.py +712 -0
  329. tnfr/validation/rules.py +253 -0
  330. tnfr/validation/rules.pyi +44 -0
  331. tnfr/validation/runtime.py +279 -0
  332. tnfr/validation/runtime.pyi +28 -0
  333. tnfr/validation/sequence_validator.py +162 -0
  334. tnfr/validation/soft_filters.py +170 -0
  335. tnfr/validation/soft_filters.pyi +32 -0
  336. tnfr/validation/spectral.py +164 -0
  337. tnfr/validation/spectral.pyi +42 -0
  338. tnfr/validation/validator.py +1266 -0
  339. tnfr/validation/window.py +39 -0
  340. tnfr/validation/window.pyi +1 -0
  341. tnfr/visualization/__init__.py +98 -0
  342. tnfr/visualization/cascade_viz.py +256 -0
  343. tnfr/visualization/hierarchy.py +284 -0
  344. tnfr/visualization/sequence_plotter.py +784 -0
  345. tnfr/viz/__init__.py +60 -0
  346. tnfr/viz/matplotlib.py +278 -0
  347. tnfr/viz/matplotlib.pyi +35 -0
  348. tnfr-8.5.0.dist-info/METADATA +573 -0
  349. tnfr-8.5.0.dist-info/RECORD +353 -0
  350. tnfr-8.5.0.dist-info/entry_points.txt +3 -0
  351. tnfr-3.0.3.dist-info/licenses/LICENSE.txt → tnfr-8.5.0.dist-info/licenses/LICENSE.md +1 -1
  352. tnfr/constants.py +0 -183
  353. tnfr/dynamics.py +0 -543
  354. tnfr/helpers.py +0 -198
  355. tnfr/main.py +0 -37
  356. tnfr/operators.py +0 -296
  357. tnfr-3.0.3.dist-info/METADATA +0 -35
  358. tnfr-3.0.3.dist-info/RECORD +0 -13
  359. {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
  360. {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,358 @@
1
+ """Cycle detection and validation for regenerative TNFR sequences.
2
+
3
+ This module implements R5_REGENERATIVE_CYCLES validation, ensuring that
4
+ regenerative cycles are structurally valid and self-sustaining according
5
+ to TNFR canonical principles.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from enum import Enum
11
+ from typing import TYPE_CHECKING, Any, Sequence
12
+
13
+ if TYPE_CHECKING:
14
+ from .grammar import StructuralPattern
15
+
16
+ from ..compat.dataclass import dataclass
17
+ from ..config.operator_names import (
18
+ COHERENCE,
19
+ COUPLING,
20
+ EMISSION,
21
+ RECEPTION,
22
+ RECURSIVITY,
23
+ RESONANCE,
24
+ SELF_ORGANIZATION,
25
+ SILENCE,
26
+ TRANSITION,
27
+ )
28
+
29
+ # Define stabilizers using canonical operator names (not glyph codes)
30
+ # These operators provide structural stability in TNFR sequences.
31
+ # Note: This uses canonical names (coherence, resonance, etc.) rather than
32
+ # glyph codes (IL, RA, etc.) from config.constants.STABILIZERS to match
33
+ # the sequence validation format throughout the system.
34
+ _STABILIZERS_SET = frozenset(
35
+ [COHERENCE, SELF_ORGANIZATION, SILENCE, RESONANCE, COUPLING]
36
+ )
37
+
38
+ __all__ = [
39
+ "REGENERATORS",
40
+ "MIN_CYCLE_LENGTH",
41
+ "MAX_CYCLE_LENGTH",
42
+ "CycleType",
43
+ "CycleAnalysis",
44
+ "CycleDetector",
45
+ ]
46
+
47
+ # Regenerators: operators that enable structural renewal and regeneration
48
+ REGENERATORS = [TRANSITION, RECURSIVITY, SILENCE] # NAV, REMESH, SHA
49
+
50
+ # Cycle length constraints
51
+ MIN_CYCLE_LENGTH = 5 # Minimum operators for meaningful cyclic behavior
52
+ MAX_CYCLE_LENGTH = 13 # Maximum = all canonical operators once
53
+
54
+
55
+ class CycleType(Enum):
56
+ """Types of regenerative cycles based on dominant regenerator."""
57
+
58
+ LINEAR = "linear" # Traditional non-cyclic sequence
59
+ REGENERATIVE = "regenerative" # Cycle with regenerators
60
+ RECURSIVE = "recursive" # REMESH-driven (fractal regeneration)
61
+ MEDITATIVE = "meditative" # SHA-driven (paused renewal)
62
+ TRANSFORMATIVE = "transformative" # NAV-driven (phase transition)
63
+
64
+
65
+ @dataclass(slots=True)
66
+ class CycleAnalysis:
67
+ """Results of regenerative cycle analysis."""
68
+
69
+ is_valid_regenerative: bool
70
+ reason: str = ""
71
+ cycle_type: CycleType = CycleType.LINEAR
72
+ health_score: float = 0.0
73
+ regenerator_position: int = -1
74
+ stabilizer_count_before: int = 0
75
+ stabilizer_count_after: int = 0
76
+ balance_score: float = 0.0
77
+ diversity_score: float = 0.0
78
+ coherence_score: float = 0.0
79
+
80
+
81
+ class CycleDetector:
82
+ """Detects and validates regenerative cycles in TNFR sequences.
83
+
84
+ Implements R5_REGENERATIVE_CYCLES validation rules:
85
+ - Cycles must have minimum length (MIN_CYCLE_LENGTH)
86
+ - Must include stabilizers before AND after regenerator
87
+ - Must achieve minimum structural health score (>0.6)
88
+ - Validates balance, diversity, and coherence
89
+
90
+ Note: Uses _STABILIZERS_SET with canonical operator names to match
91
+ the sequence validation format. Reuses pattern detector methods for
92
+ balance, diversity, and health calculations to avoid code duplication.
93
+ """
94
+
95
+ # Minimum health score for valid regenerative cycle
96
+ MIN_HEALTH_SCORE = 0.6
97
+
98
+ def analyze_potential_cycle(
99
+ self, sequence: Sequence[str], regenerator_index: int
100
+ ) -> CycleAnalysis:
101
+ """Analyze if a regenerator creates a valid regenerative cycle.
102
+
103
+ Parameters
104
+ ----------
105
+ sequence : Sequence[str]
106
+ Complete operator sequence (canonical names).
107
+ regenerator_index : int
108
+ Position of the regenerator operator.
109
+
110
+ Returns
111
+ -------
112
+ CycleAnalysis
113
+ Detailed analysis of cycle validity and characteristics.
114
+ """
115
+ # 1. Check minimum length
116
+ if len(sequence) < MIN_CYCLE_LENGTH:
117
+ return CycleAnalysis(
118
+ is_valid_regenerative=False,
119
+ reason="too_short",
120
+ cycle_type=CycleType.LINEAR,
121
+ )
122
+
123
+ # 2. Check maximum length
124
+ if len(sequence) > MAX_CYCLE_LENGTH:
125
+ return CycleAnalysis(
126
+ is_valid_regenerative=False,
127
+ reason="too_long",
128
+ cycle_type=CycleType.LINEAR,
129
+ )
130
+
131
+ # 3. Verify regenerator is valid
132
+ if regenerator_index < 0 or regenerator_index >= len(sequence):
133
+ return CycleAnalysis(
134
+ is_valid_regenerative=False,
135
+ reason="invalid_regenerator_position",
136
+ cycle_type=CycleType.LINEAR,
137
+ )
138
+
139
+ regenerator = sequence[regenerator_index]
140
+ if regenerator not in REGENERATORS:
141
+ return CycleAnalysis(
142
+ is_valid_regenerative=False,
143
+ reason="not_a_regenerator",
144
+ cycle_type=CycleType.LINEAR,
145
+ )
146
+
147
+ # 4. Check stabilizers before and after regenerator
148
+ before_segment = sequence[:regenerator_index]
149
+ after_segment = sequence[regenerator_index + 1 :]
150
+
151
+ stabilizers_before = self._count_stabilizers(before_segment)
152
+ stabilizers_after = self._count_stabilizers(after_segment)
153
+
154
+ if stabilizers_before == 0 or stabilizers_after == 0:
155
+ return CycleAnalysis(
156
+ is_valid_regenerative=False,
157
+ reason="no_stabilization",
158
+ cycle_type=CycleType.LINEAR,
159
+ stabilizer_count_before=stabilizers_before,
160
+ stabilizer_count_after=stabilizers_after,
161
+ )
162
+
163
+ # 5. Calculate structural health
164
+ balance = self._calculate_balance(sequence)
165
+ diversity = self._calculate_diversity(sequence)
166
+ coherence = self._calculate_sequence_coherence(sequence)
167
+
168
+ health_score = (balance + diversity + coherence) / 3.0
169
+
170
+ # 6. Determine cycle type
171
+ cycle_type = self._determine_cycle_type(regenerator)
172
+
173
+ # 7. Validate health threshold
174
+ is_valid = health_score >= self.MIN_HEALTH_SCORE
175
+
176
+ return CycleAnalysis(
177
+ is_valid_regenerative=is_valid,
178
+ reason="valid" if is_valid else "low_health_score",
179
+ cycle_type=cycle_type,
180
+ health_score=health_score,
181
+ regenerator_position=regenerator_index,
182
+ stabilizer_count_before=stabilizers_before,
183
+ stabilizer_count_after=stabilizers_after,
184
+ balance_score=balance,
185
+ diversity_score=diversity,
186
+ coherence_score=coherence,
187
+ )
188
+
189
+ def analyze_full_cycle(self, sequence: Sequence[str]) -> CycleAnalysis:
190
+ """Analyze complete sequence for regenerative cycle properties.
191
+
192
+ Searches for regenerators in the sequence and validates the
193
+ strongest regenerative cycle found.
194
+
195
+ Parameters
196
+ ----------
197
+ sequence : Sequence[str]
198
+ Complete operator sequence (canonical names).
199
+
200
+ Returns
201
+ -------
202
+ CycleAnalysis
203
+ Analysis of the best regenerative cycle found, or
204
+ indication that sequence is not regenerative.
205
+ """
206
+ if len(sequence) < MIN_CYCLE_LENGTH:
207
+ return CycleAnalysis(
208
+ is_valid_regenerative=False,
209
+ reason="too_short",
210
+ cycle_type=CycleType.LINEAR,
211
+ )
212
+
213
+ # Find all regenerators in sequence
214
+ regenerator_positions = [
215
+ i for i, op in enumerate(sequence) if op in REGENERATORS
216
+ ]
217
+
218
+ if not regenerator_positions:
219
+ return CycleAnalysis(
220
+ is_valid_regenerative=False,
221
+ reason="no_regenerator",
222
+ cycle_type=CycleType.LINEAR,
223
+ )
224
+
225
+ # Analyze each regenerator position and keep best result
226
+ best_analysis = None
227
+ best_health = -1.0
228
+
229
+ for pos in regenerator_positions:
230
+ analysis = self.analyze_potential_cycle(sequence, pos)
231
+ if analysis.health_score > best_health:
232
+ best_health = analysis.health_score
233
+ best_analysis = analysis
234
+
235
+ return best_analysis or CycleAnalysis(
236
+ is_valid_regenerative=False,
237
+ reason="no_valid_cycle",
238
+ cycle_type=CycleType.LINEAR,
239
+ )
240
+
241
+ def _count_stabilizers(self, segment: Sequence[str]) -> int:
242
+ """Count stabilizing operators in a sequence segment.
243
+
244
+ Uses canonical operator names: coherence, self_organization, silence, resonance, coupling.
245
+ """
246
+ return sum(1 for op in segment if op in _STABILIZERS_SET)
247
+
248
+ def _calculate_balance(self, sequence: Sequence[str]) -> float:
249
+ """Calculate structural balance score (0.0-1.0).
250
+
251
+ Reuses the existing pattern detector's health calculation approach
252
+ but adapted for cycle-specific validation. Balance measures equilibrium
253
+ between stabilizing operators.
254
+ """
255
+ from .patterns import AdvancedPatternDetector
256
+
257
+ if not sequence:
258
+ return 0.0
259
+
260
+ # Use existing pattern detector for consistent health metrics
261
+ detector = AdvancedPatternDetector()
262
+ health_metrics = detector._calculate_health_metrics(sequence)
263
+
264
+ # Adapt balance calculation for cycle validation
265
+ # Cycles need good balance (not too much stabilization, not too chaotic)
266
+ balance_raw = health_metrics.get("balance", 0.0)
267
+
268
+ # Normalize: optimal balance is around 0.2-0.4 (slightly more stabilizers)
269
+ # Convert to 0-1 score where 0.3 is optimal
270
+ if -0.1 <= balance_raw <= 0.5:
271
+ # Good range
272
+ score = 1.0 - abs(balance_raw - 0.3) * 1.5
273
+ else:
274
+ # Outside good range
275
+ score = max(0.0, 0.5 - abs(balance_raw - 0.3) * 0.5)
276
+
277
+ return max(0.0, min(1.0, score))
278
+
279
+ def _calculate_diversity(self, sequence: Sequence[str]) -> float:
280
+ """Calculate operator diversity score (0.0-1.0).
281
+
282
+ Reuses complexity calculation from AdvancedPatternDetector which
283
+ includes diversity as a component.
284
+ """
285
+ from .patterns import AdvancedPatternDetector
286
+
287
+ if not sequence:
288
+ return 0.0
289
+
290
+ detector = AdvancedPatternDetector()
291
+ # Complexity includes diversity as a factor
292
+ complexity = detector._calculate_complexity(sequence)
293
+
294
+ # For cycles, we primarily care about diversity component
295
+ unique_count = len(set(sequence))
296
+ total_count = len(sequence)
297
+ diversity_ratio = unique_count / total_count
298
+
299
+ # Bonus for using many unique operators (> 5)
300
+ if unique_count >= 5:
301
+ bonus = min(0.2, (unique_count - 5) * 0.05)
302
+ diversity_ratio = min(1.0, diversity_ratio + bonus)
303
+
304
+ return diversity_ratio
305
+
306
+ def _calculate_sequence_coherence(self, sequence: Sequence[str]) -> float:
307
+ """Calculate structural coherence score (0.0-1.0).
308
+
309
+ Combines insights from pattern detector with cycle-specific
310
+ coherence requirements (good start/end, essential elements).
311
+ """
312
+ from .patterns import AdvancedPatternDetector
313
+
314
+ if not sequence:
315
+ return 0.0
316
+
317
+ detector = AdvancedPatternDetector()
318
+ health_metrics = detector._calculate_health_metrics(sequence)
319
+
320
+ score = 0.0
321
+
322
+ # 1. Good start (emission or reception)
323
+ if sequence[0] in {EMISSION, RECEPTION, COHERENCE}:
324
+ score += 0.25
325
+
326
+ # 2. Good ending (check has_closure from health metrics)
327
+ if health_metrics.get("has_closure", False):
328
+ score += 0.25
329
+
330
+ # 3. Contains coupling (network integration)
331
+ if COUPLING in sequence:
332
+ score += 0.15
333
+
334
+ # 4. Contains resonance (amplification)
335
+ if RESONANCE in sequence:
336
+ score += 0.15
337
+
338
+ # 5. Has emission or reception (information flow)
339
+ if EMISSION in sequence or RECEPTION in sequence:
340
+ score += 0.10
341
+
342
+ # 6. Bonus for cyclic closure (starts and ends with stabilizers)
343
+ if len(sequence) >= 2:
344
+ if sequence[0] in _STABILIZERS_SET and sequence[-1] in _STABILIZERS_SET:
345
+ score += 0.10
346
+
347
+ return min(1.0, score)
348
+
349
+ def _determine_cycle_type(self, regenerator: str) -> CycleType:
350
+ """Determine cycle type based on dominant regenerator."""
351
+ if regenerator == TRANSITION:
352
+ return CycleType.TRANSFORMATIVE # NAV
353
+ elif regenerator == RECURSIVITY:
354
+ return CycleType.RECURSIVE # REMESH
355
+ elif regenerator == SILENCE:
356
+ return CycleType.MEDITATIVE # SHA
357
+ else:
358
+ return CycleType.REGENERATIVE # Generic