IndisputableMonolith.Complexity.SAT.PC
IndisputableMonolith/Complexity/SAT/PC.lean · 276 lines · 23 declarations
show as:
view math explainer →
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