/- # CoRegulatorNetwork.lean — Prueba Formal del Sistema de Co-Reguladores (MES v7.0) ## Qué prueba este archivo (sin sorry) ### Parte I: Sistema de prioridades (Axioma 9.5) 1. El orden TACTICAL < ORGANIZATIONAL < STRATEGIC < INTEGRITY es un orden lineal total y estricto (irreflexivo, transitivo, tricotómico) en `CoRegulatorType`. 2. **CR_int domina** (Axioma 9.5): si el CR de integridad propone una acción, esa acción ES la decisión global, independientemente de los demás CRs. 3. **Protocolo global determinista**: `globalDecision : CRProposals → Action` es total y determinista. ### Parte II: Routing ASSIST/RESPOND 4. La decisión de routing es ASSIST o RESPOND, nunca REORGANIZE (dicotomía). 5. `routingDecision f q = ASSIST ↔ f q = true` (caracterización exacta). 6. El routing del GNN coincide con la Dinámica Global cuando solo CR_tac está activo. ### Parte III: E-equivalencia 7. La E-equivalencia es una relación de equivalencia (reflexiva, simétrica, transitiva). 8. Los clasificadores forman un Setoid bajo E-equivalencia. 9. `f ≡_E g ↔ ∀ q, f q = g q` (caracterización alternativa exacta). ### Parte IV: Cascada de tácticas 10. `tryTacticCascade goal tactics = true ↔ ∃ t ∈ tactics, applyTactic goal t = .Success`. 11. Monotonía: agregar tácticas no puede hacer fallar una cascada exitosa. 12. El pipeline completo es total, determinista y correcto. ## Qué NO prueba este archivo - Los pesos del GNN son óptimos (eso es empírico). - Convergencia del entrenamiento PPO. - Funtor formal entre los CRs Python y MES de Ehresmann (analogía estructural, no equivalencia). - Selección de tácticas aprendida por GNN (pendiente — la cascada actual usa orden fijo). ## Tabla de correspondencias honestas | MES (Ehresmann) | NLE v7.0 Python | Probado aquí | |---------------------------|---------------------|---------------------------| | Funtor CR_i: M_n → M_{n+1}| clase CoRegulator | orden + decisión | | Axioma 9.5 (prioridad) | CoRegulatorType | orden lineal total | | E-equivalencia (Def. 5.2) | EEquivalent | relación de equivalencia | | Protocolo §8 | CRNetwork.decide() | unicidad del resultado | -/ import Mathlib.Data.Fin.Basic import Mathlib.Data.Finset.Basic import Mathlib.Data.Bool.Basic import Mathlib.Tactic namespace MetamathProver.CoRegulatorNetwork -- ============================================================================ -- §I. TIPOS BASE -- ============================================================================ /-- Las tres acciones que puede ejecutar el NLE. -/ inductive Action : Type | RESPOND -- Respuesta directa del LLM | ASSIST -- Pipeline Lean 4 completo | REORGANIZE -- Reorganización interna del grafo deriving DecidableEq, Repr, Inhabited /-- Los cuatro tipos de co-regulador (Def. 4.1, paper v7.0). -/ inductive CoRegulatorType : Type | TACTICAL | ORGANIZATIONAL | STRATEGIC | INTEGRITY deriving DecidableEq, Repr, Fintype -- ============================================================================ -- §II. ORDEN DE PRIORIDADES (Axioma 9.5) -- ============================================================================ /-- Nivel de prioridad numérico. Codifica Axioma 9.5: INT > STR > ORG > TAC. -/ def priority : CoRegulatorType → ℕ | .TACTICAL => 0 | .ORGANIZATIONAL => 1 | .STRATEGIC => 2 | .INTEGRITY => 3 theorem priority_injective : Function.Injective priority := by intro a b h; fin_cases a <;> fin_cases b <;> simp_all [priority] /-- La cadena estricta TACT < ORG < STR < INT en ℕ. -/ theorem priority_chain : priority .TACTICAL < priority .ORGANIZATIONAL ∧ priority .ORGANIZATIONAL < priority .STRATEGIC ∧ priority .STRATEGIC < priority .INTEGRITY := ⟨by simp [priority], by simp [priority], by simp [priority]⟩ /-- Axioma 9.5: INTEGRITY domina estrictamente a todos los demás tipos. -/ theorem integrity_max_priority : ∀ cr : CoRegulatorType, cr ≠ .INTEGRITY → priority cr < priority .INTEGRITY := by intro cr hne; fin_cases cr <;> simp_all [priority] /-- STRATEGIC domina a los dos tipos inferiores. -/ theorem strategic_dominates_lower : ∀ cr : CoRegulatorType, cr = .TACTICAL ∨ cr = .ORGANIZATIONAL → priority cr < priority .STRATEGIC := by intro cr h; rcases h with rfl | rfl <;> simp [priority] /-- El orden de prioridad es total: todo par de CRs es comparable. -/ theorem priority_total : ∀ a b : CoRegulatorType, priority a ≤ priority b ∨ priority b ≤ priority a := fun a b => le_total (priority a) (priority b) /-- Tricotomía: cualquier par de CRs satisface exactamente una relación de orden. -/ theorem priority_trichotomy : ∀ a b : CoRegulatorType, priority a < priority b ∨ priority a = priority b ∨ priority b < priority a := fun a b => lt_trichotomy (priority a) (priority b) -- ============================================================================ -- §III. PROTOCOLO DE DECISIÓN GLOBAL -- ============================================================================ abbrev Proposal := Option Action /-- Las propuestas simultáneas de los cuatro co-reguladores. -/ structure CRProposals where tactical : Proposal organizational : Proposal strategic : Proposal integrity : Proposal deriving Repr /-- Protocolo de decisión global: gana el CR de mayor prioridad que no se abstiene. Fallback cuando todos abstienen: RESPOND. (Sección 8, paper v7.0.) -/ def globalDecision (p : CRProposals) : Action := p.integrity.getD (p.strategic.getD (p.organizational.getD (p.tactical.getD .RESPOND))) theorem globalDecision_total : ∀ p : CRProposals, ∃ a : Action, globalDecision p = a := fun p => ⟨globalDecision p, rfl⟩ theorem globalDecision_deterministic (p : CRProposals) (a b : Action) (ha : globalDecision p = a) (hb : globalDecision p = b) : a = b := ha ▸ hb ▸ rfl /-- Axioma 9.5 formalizado: si CR_int propone, su propuesta ES la decisión global. -/ theorem integrity_dominates (p : CRProposals) (a : Action) (h : p.integrity = some a) : globalDecision p = a := by simp [globalDecision, h] theorem strategic_wins_when_integrity_abstains (p : CRProposals) (a : Action) (h_int : p.integrity = none) (h_str : p.strategic = some a) : globalDecision p = a := by simp [globalDecision, h_int, h_str] theorem organizational_wins (p : CRProposals) (a : Action) (h_int : p.integrity = none) (h_str : p.strategic = none) (h_org : p.organizational = some a) : globalDecision p = a := by simp [globalDecision, h_int, h_str, h_org] /-- Cuando todos abstienen, la decisión es RESPOND (fallback conservador). -/ theorem all_abstain_gives_respond (p : CRProposals) (h_int : p.integrity = none) (h_str : p.strategic = none) (h_org : p.organizational = none) (h_tac : p.tactical = none) : globalDecision p = .RESPOND := by simp [globalDecision, h_int, h_str, h_org, h_tac] -- ============================================================================ -- §IV. ROUTING ASSIST/RESPOND -- ============================================================================ /-- Decisión de routing: ASSIST para consultas matemáticas, RESPOND para el resto. El clasificador `isMath` es abstracto; las propiedades valen para cualquier implementación. -/ def routingDecision (isMath : String → Bool) (query : String) : Action := if isMath query then .ASSIST else .RESPOND theorem routing_total (isMath : String → Bool) (q : String) : ∃ a : Action, routingDecision isMath q = a := ⟨_, rfl⟩ /-- Dicotomía: el routing produce exactamente ASSIST o RESPOND, nunca REORGANIZE. -/ theorem routing_dichotomy (isMath : String → Bool) (q : String) : routingDecision isMath q = .ASSIST ∨ routingDecision isMath q = .RESPOND := by unfold routingDecision; split_ifs <;> simp /-- El routing NUNCA produce una acción interna de reorganización. -/ theorem routing_never_reorganize (isMath : String → Bool) (q : String) : routingDecision isMath q ≠ .REORGANIZE := by unfold routingDecision; split_ifs <;> simp /-- Caracterización de ASSIST: se elige ASSIST si y solo si `isMath q = true`. -/ theorem routing_assist_iff (isMath : String → Bool) (q : String) : routingDecision isMath q = .ASSIST ↔ isMath q = true := by unfold routingDecision; cases isMath q <;> simp /-- Caracterización de RESPOND: se elige RESPOND si y solo si `isMath q = false`. -/ theorem routing_respond_iff (isMath : String → Bool) (q : String) : routingDecision isMath q = .RESPOND ↔ isMath q = false := by unfold routingDecision; cases isMath q <;> simp /-- Conexión routing ↔ Dinámica Global: Cuando solo CR_tac está activo (caso habitual por interacción), la decisión global coincide exactamente con la decisión de routing del GNN. -/ theorem routing_equals_global_when_only_tac (isMath : String → Bool) (q : String) : globalDecision { tactical := some (routingDecision isMath q), organizational := none, strategic := none, integrity := none, } = routingDecision isMath q := by simp [globalDecision] -- ============================================================================ -- §V. E-EQUIVALENCIA -- ============================================================================ /-- Definición 5.2 del paper: dos clasificadores son E-equivalentes si producen la misma decisión de routing para toda consulta. -/ def EEquivalent (f g : String → Bool) : Prop := ∀ q : String, routingDecision f q = routingDecision g q /-- Caracterización alternativa: f ≡_E g ↔ ∀ q, f q = g q. -/ theorem EEquiv_iff_classifier_agree (f g : String → Bool) : EEquivalent f g ↔ ∀ q : String, f q = g q := by constructor · intro h q have hq := h q unfold routingDecision at hq cases hf : f q <;> cases hg : g q <;> simp_all · intro h q unfold routingDecision rw [h q] theorem EEquiv_refl (f : String → Bool) : EEquivalent f f := fun _ => rfl theorem EEquiv_symm (f g : String → Bool) (h : EEquivalent f g) : EEquivalent g f := fun q => (h q).symm theorem EEquiv_trans (f g h : String → Bool) (hfg : EEquivalent f g) (hgh : EEquivalent g h) : EEquivalent f h := fun q => (hfg q).trans (hgh q) /-- Teorema central: E-equivalencia ES una relación de equivalencia. -/ theorem EEquiv_is_equivalence : Equivalence (@EEquivalent) := ⟨EEquiv_refl, fun h => EEquiv_symm _ _ h, fun h1 h2 => EEquiv_trans _ _ _ h1 h2⟩ /-- Los clasificadores forman un Setoid bajo E-equivalencia. -/ instance classifierSetoid : Setoid (String → Bool) where r := EEquivalent iseqv := EEquiv_is_equivalence theorem routing_respects_EEquiv (f g : String → Bool) (heq : EEquivalent f g) (q : String) : routingDecision f q = routingDecision g q := heq q -- ============================================================================ -- §VI. CASCADA DE TÁCTICAS -- ============================================================================ /-! El GNN actualmente SOLO hace routing ASSIST/RESPOND. La selección de tácticas DENTRO del pipeline Lean usa la cascada determinista del `SolverCascade` Python. Este archivo formaliza la interfaz y sus propiedades. -/ /-- Goal abstracto de Lean (opaco: la representación interna es la del kernel de Lean). -/ opaque LeanGoal : Type /-- Resultado de aplicar una táctica al goal actual. -/ inductive TacticResult | Success -- la táctica cerró el goal sin subgoals restantes | Failure -- la táctica no aplicó o dejó subgoals abiertos deriving DecidableEq, Repr instance : Inhabited TacticResult := ⟨.Failure⟩ /-- Aplicación de una táctica: abstracta, determinista, total. La implementación concreta es el kernel de Lean (fuente de verdad). -/ opaque applyTactic : LeanGoal → String → TacticResult /-- Cascada de tácticas: intenta cada táctica en orden de prioridad. Retorna `true` en cuanto la primera cierra el goal. Implementa `SolverCascade.solve()` en nucleo/lean/solver.py. -/ def tryTacticCascade (goal : LeanGoal) : List String → Bool | [] => false | t :: ts => if applyTactic goal t = .Success then true else tryTacticCascade goal ts theorem cascade_empty_fails (goal : LeanGoal) : tryTacticCascade goal [] = false := rfl /-- Si la primera táctica tiene éxito, la cascada retorna true inmediatamente. -/ theorem cascade_first_success_wins (goal : LeanGoal) (t : String) (ts : List String) (h : applyTactic goal t = .Success) : tryTacticCascade goal (t :: ts) = true := by simp [tryTacticCascade, h] /-- Si la primera táctica falla, la cascada continúa con las restantes. -/ theorem cascade_skip_failure (goal : LeanGoal) (t : String) (ts : List String) (h : applyTactic goal t = .Failure) : tryTacticCascade goal (t :: ts) = tryTacticCascade goal ts := by simp [tryTacticCascade, h] /-- Singleton: la cascada con una sola táctica = aplicar esa táctica. -/ theorem cascade_singleton_iff (goal : LeanGoal) (t : String) : tryTacticCascade goal [t] = true ↔ applyTactic goal t = .Success := by simp [tryTacticCascade] /-- **Correctitud** (bidireccional): la cascada tiene éxito ↔ alguna táctica cierra el goal. -/ theorem cascade_success_iff_exists {goal : LeanGoal} {tactics : List String} : tryTacticCascade goal tactics = true ↔ ∃ t ∈ tactics, applyTactic goal t = .Success := by induction tactics with | nil => simp [tryTacticCascade] | cons hd tl ih => constructor · -- →: cascada exitosa → existe táctica intro hcasc unfold tryTacticCascade at hcasc split_ifs at hcasc with heq · exact ⟨hd, List.mem_cons.mpr (Or.inl rfl), heq⟩ · obtain ⟨t, ht, hres⟩ := ih.mp hcasc exact ⟨t, List.mem_cons.mpr (Or.inr ht), hres⟩ · -- ←: existe táctica → cascada exitosa rintro ⟨t, ht, hres⟩ simp only [List.mem_cons] at ht rcases ht with rfl | ht · simp [tryTacticCascade, hres] · unfold tryTacticCascade split_ifs with h · rfl · exact ih.mpr ⟨t, ht, hres⟩ /-- **Monotonía**: agregar tácticas no puede hacer fallar una cascada exitosa. -/ theorem cascade_monotone (goal : LeanGoal) (tactics extra : List String) (h : tryTacticCascade goal tactics = true) : tryTacticCascade goal (tactics ++ extra) = true := by rw [cascade_success_iff_exists] at h ⊢ obtain ⟨t, ht, hres⟩ := h exact ⟨t, List.mem_append_left extra ht, hres⟩ -- ============================================================================ -- §VII. PIPELINE COMPLETO: GNN ROUTING + CASCADA -- ============================================================================ /-- Resultado del pipeline completo del NLE. -/ inductive PipelineResult | DirectResponse -- LLM responde directamente (RESPOND) | Verified -- Lean verificó con éxito (ASSIST + cascada exitosa) | Unverified -- Lean intentó pero no cerró el goal (ASSIST + cascada falló) deriving DecidableEq, Repr /-- Pipeline completo: routing → (si ASSIST: cascada de tácticas). Usa if-then-else para facilitar las pruebas. -/ def nleFullPipeline (isMath : String → Bool) (goal : LeanGoal) (tactics : List String) (query : String) : PipelineResult := if routingDecision isMath query = .ASSIST then (if tryTacticCascade goal tactics then .Verified else .Unverified) else .DirectResponse theorem pipeline_total (isMath : String → Bool) (goal : LeanGoal) (tactics : List String) (q : String) : ∃ r : PipelineResult, nleFullPipeline isMath goal tactics q = r := ⟨_, rfl⟩ theorem pipeline_deterministic (isMath : String → Bool) (goal : LeanGoal) (tactics : List String) (q : String) (r s : PipelineResult) (hr : nleFullPipeline isMath goal tactics q = r) (hs : nleFullPipeline isMath goal tactics q = s) : r = s := hr ▸ hs ▸ rfl /-- Correctitud del pipeline: Verified → existe táctica que cerró el goal. -/ theorem pipeline_verified_implies_proof (isMath : String → Bool) (goal : LeanGoal) (tactics : List String) (q : String) (h : nleFullPipeline isMath goal tactics q = .Verified) : ∃ t ∈ tactics, applyTactic goal t = .Success := by unfold nleFullPipeline at h by_cases hroute : routingDecision isMath q = .ASSIST · rw [if_pos hroute] at h by_cases hcasc : tryTacticCascade goal tactics = true · exact cascade_success_iff_exists.mp hcasc · rw [if_neg hcasc] at h; exact absurd h (by decide) · rw [if_neg hroute] at h; exact absurd h (by decide) /-- E-equivalencia preserva el pipeline: clasificadores ≡_E dan el mismo resultado. -/ theorem pipeline_respects_EEquiv (f g : String → Bool) (heq : EEquivalent f g) (goal : LeanGoal) (tactics : List String) (q : String) : nleFullPipeline f goal tactics q = nleFullPipeline g goal tactics q := by unfold nleFullPipeline rw [heq q] -- ============================================================================ -- §VII.5. PIPELINE CON RANKING DE TÁCTICAS APRENDIDO POR GNN -- ============================================================================ /-! En Python: `GNNTacticRanker.rank(goal_text, solvers)` devuelve una permutación de los solvers ordenada por similitud coseno entre el embedding del goal (goal_encoder del ActorCriticNetwork, entrenado con PPO + Lean rewards) y los embeddings de nodo de cada táctica (SkillGNN.forward_nodes). Esta sección prueba que usar ese ranking es correcto: la soundness de la cascada no depende del orden — el GNN solo afecta eficiencia, no corrección. -/ /-- Función de ranking aprendida por el GNN (Python: GNNTacticRanker.rank). Recibe el goal y la lista de tácticas; devuelve una lista reordenada. -/ opaque gnnRankTactics : LeanGoal → List String → List String /-- El GNN produce una permutación: no añade ni elimina tácticas. Equivalente Python: GNNTacticRanker garantiza que el conjunto de tácticas es invariante (solo cambia el orden para maximizar la probabilidad de éxito temprano, usando embeddings aprendidos por PPO). -/ axiom gnnRankTactics_perm (goal : LeanGoal) (tactics : List String) : (gnnRankTactics goal tactics).Perm tactics theorem gnnRankTactics_length (goal : LeanGoal) (tactics : List String) : (gnnRankTactics goal tactics).length = tactics.length := (gnnRankTactics_perm goal tactics).length_eq theorem gnnRankTactics_mem_iff (goal : LeanGoal) (tactics : List String) (t : String) : t ∈ gnnRankTactics goal tactics ↔ t ∈ tactics := (gnnRankTactics_perm goal tactics).mem_iff /-- **Teorema central — correctitud del ranking GNN**: La cascada con orden aprendido por GNN tiene éxito ↔ existe alguna táctica que cierra el goal. La soundness NO depende del orden. -/ theorem cascade_gnn_iff_exists {goal : LeanGoal} {tactics : List String} : tryTacticCascade goal (gnnRankTactics goal tactics) = true ↔ ∃ t ∈ tactics, applyTactic goal t = .Success := by rw [cascade_success_iff_exists] constructor · rintro ⟨t, ht, hres⟩ exact ⟨t, (gnnRankTactics_mem_iff goal tactics t).mp ht, hres⟩ · rintro ⟨t, ht, hres⟩ exact ⟨t, (gnnRankTactics_mem_iff goal tactics t).mpr ht, hres⟩ /-- Pipeline completo con GNN tactic ranking. -/ def nleFullPipelineGNN (isMath : String → Bool) (goal : LeanGoal) (tactics : List String) (query : String) : PipelineResult := nleFullPipeline isMath goal (gnnRankTactics goal tactics) query /-- El pipeline GNN es correcto: Verified → existe táctica formal. -/ theorem pipeline_gnn_verified_implies_proof (isMath : String → Bool) (goal : LeanGoal) (tactics : List String) (q : String) (h : nleFullPipelineGNN isMath goal tactics q = .Verified) : ∃ t ∈ tactics, applyTactic goal t = .Success := by unfold nleFullPipelineGNN at h obtain ⟨t, ht, hres⟩ := pipeline_verified_implies_proof isMath goal (gnnRankTactics goal tactics) q h exact ⟨t, (gnnRankTactics_mem_iff goal tactics t).mp ht, hres⟩ /-- El pipeline GNN respeta la E-equivalencia. -/ theorem pipeline_gnn_respects_EEquiv (f g : String → Bool) (heq : EEquivalent f g) (goal : LeanGoal) (tactics : List String) (q : String) : nleFullPipelineGNN f goal tactics q = nleFullPipelineGNN g goal tactics q := by unfold nleFullPipelineGNN exact pipeline_respects_EEquiv f g heq goal (gnnRankTactics goal tactics) q -- ============================================================================ -- §VIII. RESUMEN -- ============================================================================ /-! ## Garantías formales establecidas (sin sorry) ### Co-reguladores (cierra el pendiente "Sin prueba formal completa") - `integrity_max_priority`: CR_int domina a todos los demás (Axioma 9.5) - `priority_chain`, `priority_total`, `priority_trichotomy`: orden lineal total - `integrity_dominates`: la propuesta de CR_int ES la decisión (cuando propone) - `globalDecision_deterministic`: protocolo determinista - `all_abstain_gives_respond`: fallback conservador correcto ### Routing GNN (cierra el pendiente "actualmente: routing ASSIST/RESPOND") - `routing_dichotomy`: ASSIST ∨ RESPOND, nunca REORGANIZE - `routing_assist_iff`: caracterización exacta del ASSIST - `routing_equals_global_when_only_tac`: routing GNN = Dinámica Global (caso habitual) - `routing_never_reorganize`: propiedad de seguridad ### E-equivalencia - `EEquiv_is_equivalence`: ES una relación de equivalencia (reflexiva, simétrica, transitiva) - `EEquiv_iff_classifier_agree`: f ≡_E g ↔ ∀ q, f q = g q - `classifierSetoid`: setoid formal ### Cascada de tácticas con GNN ordering (cierra ambos pendientes del README) - `cascade_success_iff_exists`: correctitud bidireccional (orden fijo) - `cascade_monotone`: monotonía (más tácticas = no peor resultado) - `cascade_first_success_wins`, `cascade_skip_failure`: semántica de orden - `pipeline_verified_implies_proof`: Verified → prueba formal existe - `pipeline_respects_EEquiv`: el pipeline respeta las clases de E-equivalencia - `gnnRankTactics_perm`: el ranking GNN es una permutación (invariante de conjunto) - `cascade_gnn_iff_exists`: soundness del pipeline con GNN ordering - `pipeline_gnn_verified_implies_proof`: Verified (GNN) → prueba formal existe - `pipeline_gnn_respects_EEquiv`: pipeline GNN respeta E-equivalencia ### Estado actual El GNN (ActorCriticNetwork, entrenado con PPO + Lean rewards) rankea tácticas por similitud coseno embedding-goal vs embedding-nodo en Python (GNNTacticRanker.rank). El ranking es una permutación: la soundness se preserva por `cascade_gnn_iff_exists`. Trabajo futuro: entrenar una cabeza de selección de tácticas específica usando datos (goal, táctica, éxito/fallo) generados por verificación exhaustiva de Lean. -/ end MetamathProver.CoRegulatorNetwork