pith. machine review for the scientific record. sign in

IndisputableMonolith.Complexity.SAT.PC

IndisputableMonolith/Complexity/SAT/PC.lean · 276 lines · 23 declarations

show as:
view math explainer →

open module explainer GitHub source

Explainer status: pending

   1import Mathlib
   2import IndisputableMonolith.Complexity.SAT.CNF
   3import IndisputableMonolith.Complexity.SAT.XOR
   4
   5namespace IndisputableMonolith
   6namespace Complexity
   7namespace SAT
   8
   9/-- Constraints are either CNF-clauses or XOR-checks. -/
  10inductive Constraint (n : Nat) where
  11  | cnf (C : Clause n)
  12  | xor (X : XORConstraint n)
  13deriving Repr
  14
  15/-- Whether a variable is mentioned in a literal. -/
  16def mentionsVarLit {n} (l : Lit n) (v : Var n) : Bool :=
  17  match l with
  18  | .pos u => decide (u = v)
  19  | .neg u => decide (u = v)
  20
  21/-- Whether a variable is mentioned in a clause. -/
  22def mentionsVarClause {n} (C : Clause n) (v : Var n) : Bool :=
  23  C.any (fun l => mentionsVarLit l v)
  24
  25/-- Whether a variable is mentioned in an XOR constraint. -/
  26def mentionsVarXOR {n} (X : XORConstraint n) (v : Var n) : Bool :=
  27  X.vars.any (fun u => decide (u = v))
  28
  29/-- Whether a variable is mentioned in a mixed constraint. -/
  30def mentionsVar {n} (K : Constraint n) (v : Var n) : Bool :=
  31  match K with
  32  | .cnf C => mentionsVarClause C v
  33  | .xor X => mentionsVarXOR X v
  34
  35/-- Satisfaction semantics for mixed constraints. -/
  36def satisfiesConstraint {n} (a : Assignment n) (K : Constraint n) : Prop :=
  37  match K with
  38  | .cnf C => evalClause a C = true
  39  | .xor X => parityOf a X.vars = X.parity
  40
  41/-- The constraint K determines variable v w.r.t. reference assignment `aRef`:
  42    fixing all non-v variables to `aRef` and requiring `K` forces `v = aRef v`. -/
  43def determinesVar {n}
  44  (aRef : Assignment n) (K : Constraint n) (v : Var n) : Prop :=
  45  ∀ (a' : Assignment n),
  46    (∀ w : Var n, w ≠ v → a' w = aRef w) →
  47    satisfiesConstraint a' K →
  48    a' v = aRef v
  49
  50/-- Collect all constraints arising from a CNF+XOR instance. -/
  51def constraintsOf {n} (φ : CNF n) (H : XORSystem n) : List (Constraint n) :=
  52  (φ.clauses.map Constraint.cnf) ++ (H.map Constraint.xor)
  53
  54/-- Set of input variables (as a finset) for PC property articulation. -/
  55abbrev InputSet (n : Nat) := Finset (Var n)
  56
  57/-- Propagation-Completeness condition (PC):
  58    For every nonempty U ⊆ inputs, there exists a constraint K and v ∈ U such that
  59    (i) K mentions v, (ii) K mentions no other element of U, and (iii) K determines v
  60    with respect to the unique reference assignment `aRef`. -/
  61def PC {n}
  62  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) : Prop :=
  63  ∀ (U : Finset (Var n)),
  64    U ⊆ inputs →
  65    U.Nonempty →
  66    ∃ (K : Constraint n),
  67      K ∈ constraintsOf φ H ∧
  68      ∃ v ∈ U,
  69        mentionsVar K v = true ∧
  70        (∀ w ∈ U, w ≠ v → mentionsVar K w = false) ∧
  71        determinesVar aRef K v
  72
  73/-- Peeling witness structure: a list of variables and constraints meeting the peeling conditions. -/
  74structure PeelingData {n : Nat} (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) where
  75  vars : List (Var n)
  76  constrs : List (Constraint n)
  77  nodup : vars.Nodup
  78  len_eq : vars.length = constrs.length
  79  cover : ∀ v : Var n, v ∈ inputs ↔ v ∈ vars
  80  step : ∀ k (hk : k < vars.length),
  81    let v := vars.get ⟨k, hk⟩
  82    let K := constrs.get ⟨k, by omega⟩
  83    mentionsVar K v = true ∧
  84    (∀ w, w ∈ vars.drop k.succ → mentionsVar K w = false) ∧
  85    determinesVar aRef K v
  86
  87/-- Peeling witness (Prop-level): there exists a peeling structure. -/
  88def PeelingWitness {n}
  89  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) : Prop :=
  90  Nonempty (PeelingData inputs aRef φ H)
  91
  92/-- Forced-implication reachability (abstract): there is a directed arborescence
  93    of locally-determining constraints from OUTPUT to every input.
  94
  95    **Definition**: We define ForcedArborescence as equivalent to PeelingWitness.
  96    The peeling order (v₁, v₂, ..., vₙ) with determining constraints (K₁, K₂, ..., Kₙ)
  97    implicitly defines an arborescence where each variable's parent is determined
  98    by the constraint that determines it.
  99
 100    **Graph interpretation**: The arborescence edges are:
 101    - v → K_i for each variable v mentioned in K_i's "known" portion
 102    - K_i → v_i for the variable determined by K_i
 103
 104    This forms a directed tree rooted at OUTPUT reaching all input variables. -/
 105def ForcedArborescence {n}
 106  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) : Prop :=
 107  PeelingWitness inputs aRef φ H  -- Arborescence IS the peeling structure
 108
 109/-- Forced arborescence witness: for this development we take it to be the same data
 110    as a peeling witness (a spanning, duplicate-free list of vars with matching constraints). -/
 111abbrev ForcedArborescenceWitness {n}
 112  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) : Prop :=
 113  PeelingWitness inputs aRef φ H
 114
 115/-- Program goal (graph-theoretic equivalence to target):
 116    PC ↔ existence of a forced-implication arborescence (to be proven). -/
 117def programGoal_pc_iff_arborescence {n}
 118  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) : Prop :=
 119  (PC inputs aRef φ H) ↔ (ForcedArborescence inputs aRef φ H)
 120
 121/-- Helper to extract one (K, v) pair from PC condition. -/
 122noncomputable def extractFromPC {n : Nat} (inputs : InputSet n) (aRef : Assignment n)
 123    (φ : CNF n) (H : XORSystem n) (hPC : PC inputs aRef φ H)
 124    (U : Finset (Var n)) (hU : U ⊆ inputs) (hne : U.Nonempty) :
 125    { p : Constraint n × Var n //
 126      p.1 ∈ constraintsOf φ H ∧
 127      p.2 ∈ U ∧
 128      mentionsVar p.1 p.2 = true ∧
 129      (∀ w ∈ U, w ≠ p.2 → mentionsVar p.1 w = false) ∧
 130      determinesVar aRef p.1 p.2 } := by
 131  have h := hPC U hU hne
 132  choose K hK using h
 133  choose v hv using hK.2
 134  exact ⟨(K, v), hK.1, hv.1, hv.2.1, hv.2.2.1, hv.2.2.2⟩
 135
 136/-- Bundled result type for peeling construction. -/
 137structure PeelingResult {n : Nat} (inputs : InputSet n) (aRef : Assignment n)
 138    (φ : CNF n) (H : XORSystem n) (U : Finset (Var n)) where
 139  vars : List (Var n)
 140  constrs : List (Constraint n)
 141  len_eq : vars.length = constrs.length
 142  nodup : vars.Nodup
 143  cover : ∀ v, v ∈ vars ↔ v ∈ U
 144  step : ∀ k (hk : k < vars.length),
 145    let v := vars.get ⟨k, hk⟩
 146    let K := constrs.get ⟨k, by omega⟩
 147    mentionsVar K v = true ∧
 148    (∀ w ∈ vars.drop k.succ, mentionsVar K w = false) ∧
 149    determinesVar aRef K v
 150
 151/-- **PROVED**: Build the peeling order via Finset induction.
 152    At each step, PC gives constraint K and variable v ∈ U that K uniquely determines.
 153    Recursively peel U \ {v} to get (vs, cs), then return (v :: vs, K :: cs). -/
 154noncomputable def buildPeelingResult {n : Nat} (inputs : InputSet n) (aRef : Assignment n)
 155    (φ : CNF n) (H : XORSystem n) (hPC : PC inputs aRef φ H)
 156    (U : Finset (Var n)) (hU : U ⊆ inputs) :
 157    PeelingResult inputs aRef φ H U := by
 158  induction' hcard : U.card with k ih generalizing U
 159  · -- Base case: U is empty
 160    exact {
 161      vars := []
 162      constrs := []
 163      len_eq := rfl
 164      nodup := List.nodup_nil
 165      cover := by intro v; simp; rw [Finset.card_eq_zero.mp hcard]; exact Finset.not_mem_empty v
 166      step := by intro k hk; simp at hk
 167    }
 168  · -- Inductive case: U is nonempty
 169    have hne : U.Nonempty := Finset.card_pos.mp (by omega)
 170    let ⟨⟨K, v⟩, _, hvmem, hment, honly, hdet⟩ := extractFromPC inputs aRef φ H hPC U hU hne
 171    let U' := U.erase v
 172    have hU' : U' ⊆ inputs := fun w hw => hU (Finset.mem_erase.mp hw).2
 173    have hcard' : U'.card = k := by rw [Finset.card_erase_of_mem hvmem]; omega
 174    let rec_result := ih U' hU' hcard'
 175    exact {
 176      vars := v :: rec_result.vars
 177      constrs := K :: rec_result.constrs
 178      len_eq := by simp only [List.length_cons, rec_result.len_eq]
 179      nodup := by
 180        refine List.Nodup.cons ?_ rec_result.nodup
 181        intro hv_in_vs
 182        have hv_in_U' := (rec_result.cover v).mp hv_in_vs
 183        exact (Finset.not_mem_erase v U) hv_in_U'
 184      cover := by
 185        intro w
 186        simp only [List.mem_cons]
 187        constructor
 188        · intro hw
 189          rcases hw with rfl | hw'
 190          · exact hvmem
 191          · exact Finset.mem_of_mem_erase ((rec_result.cover w).mp hw')
 192        · intro hw
 193          by_cases hwv : w = v
 194          · left; exact hwv
 195          · right; exact (rec_result.cover w).mpr (Finset.mem_erase.mpr ⟨hwv, hw⟩)
 196      step := by
 197        intro idx hidx
 198        simp only [List.length_cons] at hidx
 199        cases idx with
 200        | zero =>
 201          simp only [List.drop_succ_cons, List.drop_zero]
 202          constructor
 203          · exact hment
 204          constructor
 205          · intro w hw
 206            have hw_in_U' := (rec_result.cover w).mp hw
 207            have hw_in_U := Finset.mem_of_mem_erase hw_in_U'
 208            have hw_ne_v : w ≠ v := fun heq => by
 209              rw [heq] at hw_in_U'
 210              exact (Finset.not_mem_erase v U) hw_in_U'
 211            exact honly w hw_in_U hw_ne_v
 212          · exact hdet
 213        | succ idx' =>
 214          simp only [List.drop_succ_cons]
 215          have hidx' : idx' < rec_result.vars.length := by simp at hidx; omega
 216          exact rec_result.step idx' hidx'
 217    }
 218
 219/-- **PROVED**: PC ⇒ peeling.
 220    If the PC condition holds for inputs, we can construct a peeling witness.
 221
 222    **Proof**: Classical Finset induction via `buildPeelingResult`. At each step:
 223    1. Given nonempty U ⊆ inputs, PC gives constraint K and variable v ∈ U
 224    2. K mentions only v from U, and determines v
 225    3. Recursively peel U \ {v} to get (vs, cs)
 226    4. Return (v :: vs, K :: cs)
 227
 228    Base case: empty U gives ([], []). -/
 229theorem pc_implies_peeling {n}
 230  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) :
 231  PC inputs aRef φ H → PeelingWitness inputs aRef φ H := by
 232  intro hPC
 233  let result := buildPeelingResult inputs aRef φ H hPC inputs (fun _ h => h)
 234  exact ⟨{
 235    vars := result.vars
 236    constrs := result.constrs
 237    nodup := result.nodup
 238    len_eq := result.len_eq
 239    cover := fun v => (result.cover v).symm
 240    step := result.step
 241  }⟩
 242
 243/-- Peeling ⇒ forced arborescence (Prop-level).
 244    Trivial since ForcedArborescence is defined as PeelingWitness. -/
 245theorem peeling_implies_arborescence {n}
 246  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) :
 247  PeelingWitness inputs aRef φ H → ForcedArborescence inputs aRef φ H := by
 248  unfold ForcedArborescence
 249  exact id
 250
 251/-- Arborescence ⇒ peeling (Prop-level).
 252    Trivial since ForcedArborescence is defined as PeelingWitness. -/
 253theorem arborescence_implies_peeling {n}
 254  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) :
 255  ForcedArborescence inputs aRef φ H → PeelingWitness inputs aRef φ H := by
 256  unfold ForcedArborescence
 257  exact id
 258
 259/-- Peeling ↔ Arborescence equivalence. -/
 260theorem peeling_iff_arborescence {n}
 261  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) :
 262  PeelingWitness inputs aRef φ H ↔ ForcedArborescence inputs aRef φ H := by
 263  unfold ForcedArborescence
 264  exact Iff.rfl
 265
 266/-- PC ⇒ ForcedArborescence. -/
 267theorem pc_implies_forcedArborescence {n}
 268  (inputs : InputSet n) (aRef : Assignment n) (φ : CNF n) (H : XORSystem n) :
 269  PC inputs aRef φ H → ForcedArborescence inputs aRef φ H := by
 270  unfold ForcedArborescence
 271  exact pc_implies_peeling inputs aRef φ H
 272
 273end SAT
 274end Complexity
 275end IndisputableMonolith
 276

source mirrored from github.com/jonwashburn/shape-of-logic