Documentation

LeanPool.Sundogcert.SATReductionForward

Sundogcert/SATReductionForward.lean — MILESTONE 8 of the 3SAT ≤ 3DM marathon: the FORWARD DIRECTION of the reduction's correctness, and the analytic crux of the whole reduction.

WHAT THIS FILE PROVES (forward): Satisfiable φ → threeDMI (tripleFn φ) — a satisfying assignment for the formula φ yields a perfect 3-dimensional matching of the gadget triple map. This is the hard direction: it must EXHIBIT the matching explicitly and then verify all three cover conditions (each W-, X-, and Y-element hit exactly once).

THE CONSTRUCTION (pure combinatorics, all inside the proof). From a satisfying assignment a and a per-clause witness slot slotStar k (choose from sat), build three triple families: * WHEEL triples — one per (i, j): wheelTriple ij = negT i j if a i, else posT i j. The tip it consumes is (i, j, !(a i)); so a tip (i, j, s) is FREE (unconsumed) iff s = a i. * CLAUSE triples — one per clause k: clauseT k (slotStar k), whose W-tip ((φ k (slotStar k)).1, k, (φ k (slotStar k)).2) is a free tip (the witness literal is true, so its sign matches a at its variable — hlitfree). These m tips are the CLAIMED tips. * GARBAGE triples — one per g : Fin (m·(n-1)): garbageT g (β g), where β bijects Fin (m·(n-1)) onto the UNCLAIMED free tips (freeTips \ claimedTips; the count n·m − m = m·(n−1) uses n ≥ 1, and the bijection comes from Fintype.equivFinOfCardEq). The matching T is the union of the three image families.

THE THREE COVER CONDITIONS. Because the three families live in DISJOINT Sum summands of TripleIdx, any predicate's filtered count over T splits as wheel + clause + garbage (hsplit), and each part — an image of an injective map over univ — reduces to a univ-filter count (hredWheel/hredClause/hredGarbage). Then: * W-condition: each tip (i, j, s) is hit once — CONSUMED → (1,0,0); free & CLAIMED → (0,1,0); free & UNCLAIMED → (0,0,1). * X-condition: an a-node is hit by exactly one wheel triple (the CYCLIC spoke shift, via xcoord_inl); an s1/g1-node by exactly the matching clause/garbage triple (xcoord_s1/g1). * Y-condition: a b-node by exactly the single wheel triple at (i, j) (NO cyclic shift, ycoord_inl); an s2/g2-node by the matching clause/garbage triple (ycoord_s2/g2).

STANDING LIMIT: this module proves ONLY the forward direction. The reverse direction (threeDMI (tripleFn φ) → Satisfiable φ) is milestone 7 (Sundogcert/SATReductionReverse.lean), and the index-bridge to the Fin s-indexed MatchingNPHard.ThreeDM is milestone 5 (Sundogcert/ThreeDMReindex.lean). Nothing here is claimed about NP-hardness itself.

NOTE on synthInstance.maxSize: DecidableEq (TripleIdx n m) (a 4-way nested Sum of products) does not synthesize at the default maxSize inside this large proof context; a scoped set_option synthInstance.maxSize 512 in on forward clears it (as in m7).

Axiom-clean (no native_decide, no decide). Expect [propext, Classical.choice, Quot.sound].

theorem Sundog.SATReductionForward.wfibre_cover {n m : } [NeZero m] (φ : SATNPHard.Formula n m) (a : SATNPHard.Assignment n) (slotStar : Fin mFin 3) (wheelTriple : Fin n × Fin mSATReduction.TripleIdx n m) (beta : Fin (m * (n - 1))SATReduction.Tip n m) (freeTips claimedTips unclaimed : Finset (SATReduction.Tip n m)) (T : Finset (SATReduction.TripleIdx n m)) (hsplit : ∀ (P : SATReduction.TripleIdx n mProp) [inst : DecidablePred P], (Finset.filter P T).card = {ij : Fin n × Fin m | P (wheelTriple ij)}.card + {k : Fin m | P (SATReductionIncidence.clauseT k (slotStar k))}.card + {g : Fin (m * (n - 1)) | P (SATReductionIncidence.garbageT g (beta g))}.card) (hwheeltip : ∀ (ij : Fin n × Fin m), (SATReduction.tripleFn φ (wheelTriple ij)).1 = (ij.1, ij.2, !a ij.1)) (hclausetip : ∀ (k : Fin m), (SATReduction.tripleFn φ (SATReductionIncidence.clauseT k (slotStar k))).1 = ((φ k (slotStar k)).1, k, (φ k (slotStar k)).2)) (hgarbagetip : ∀ (g : Fin (m * (n - 1))), (SATReduction.tripleFn φ (SATReductionIncidence.garbageT g (beta g))).1 = beta g) (hbeta_mem : ∀ (g : Fin (m * (n - 1))), beta g unclaimed) (hbeta_inj : Function.Injective beta) (hbeta_surj : wunclaimed, ∃ (g : Fin (m * (n - 1))), beta g = w) (hsub : claimedTips freeTips) (hfreeTips : freeTips = {tau : SATReduction.Tip n m | tau.2.2 = a tau.1}) (hclaimedTips : claimedTips = Finset.image (fun (k : Fin m) => ((φ k (slotStar k)).1, k, (φ k (slotStar k)).2)) Finset.univ) (hunclaimed : unclaimed = freeTips \ claimedTips) (w : SATReduction.Tip n m) :
{idxT | (SATReduction.tripleFn φ idx).1 = w}.card = 1

The W-fibre (tip) cover condition of the forward matching, factored out of forward.

Given the disjoint-split reduction hsplit, the per-family univ-filter reductions hred*, and the per-family tip characterizations h*tip, every tip w is covered exactly once by the matching: consumed → wheel hits it once; free & claimed → the clause triple; free & unclaimed → the garbage triple.

theorem Sundog.SATReductionForward.xnode_cover {n m : } [NeZero m] (φ : SATNPHard.Formula n m) (a : SATNPHard.Assignment n) (slotStar : Fin mFin 3) (wheelTriple : Fin n × Fin mSATReduction.TripleIdx n m) (beta : Fin (m * (n - 1))SATReduction.Tip n m) (T : Finset (SATReduction.TripleIdx n m)) (hsplit : ∀ (P : SATReduction.TripleIdx n mProp) [inst : DecidablePred P], (Finset.filter P T).card = {ij : Fin n × Fin m | P (wheelTriple ij)}.card + {k : Fin m | P (SATReductionIncidence.clauseT k (slotStar k))}.card + {g : Fin (m * (n - 1)) | P (SATReductionIncidence.garbageT g (beta g))}.card) (hwheelDef : ∀ (ij : Fin n × Fin m), wheelTriple ij = if a ij.1 = true then SATReductionIncidence.negT ij.1 ij.2 else SATReductionIncidence.posT ij.1 ij.2) (hwheel_form : ∀ (ij : Fin n × Fin m), wheelTriple ij = SATReductionIncidence.negT ij.1 ij.2 wheelTriple ij = SATReductionIncidence.posT ij.1 ij.2) (x : SATReduction.XNode n m) :
{idxT | (SATReduction.tripleFn φ idx).2.1 = x}.card = 1

The X-node cover condition of the forward matching, factored out of forward.

Each a-node inl (i,j) is hit by exactly one wheel triple (the cyclic spoke shift); each s1-node by exactly its clause triple; each g1-node by exactly its garbage triple.

theorem Sundog.SATReductionForward.ynode_cover {n m : } [NeZero m] (φ : SATNPHard.Formula n m) (slotStar : Fin mFin 3) (wheelTriple : Fin n × Fin mSATReduction.TripleIdx n m) (beta : Fin (m * (n - 1))SATReduction.Tip n m) (T : Finset (SATReduction.TripleIdx n m)) (hsplit : ∀ (P : SATReduction.TripleIdx n mProp) [inst : DecidablePred P], (Finset.filter P T).card = {ij : Fin n × Fin m | P (wheelTriple ij)}.card + {k : Fin m | P (SATReductionIncidence.clauseT k (slotStar k))}.card + {g : Fin (m * (n - 1)) | P (SATReductionIncidence.garbageT g (beta g))}.card) (hwheel_form : ∀ (ij : Fin n × Fin m), wheelTriple ij = SATReductionIncidence.negT ij.1 ij.2 wheelTriple ij = SATReductionIncidence.posT ij.1 ij.2) (y : SATReduction.YNode n m) :
{idxT | (SATReduction.tripleFn φ idx).2.2 = y}.card = 1

The Y-node cover condition of the forward matching, factored out of forward.

Each b-node inl (i,j) is hit by exactly one wheel triple (no cyclic shift on the Y side); each s2-node by exactly its clause triple; each g2-node by exactly its garbage triple.