Imports
The CLRS 3-CNF-SAT to SUBSET-SUM construction
There are two indexed items per variable and three unit slack items per clause. Variable columns target one; clause columns target four. Three unit slack copies are equivalent to the textbook's weight-one and weight-two pair, while making the finite-item accounting more uniform.
namespace CLRS.Chapter34.SubsetSumReductionLiteral represented by choosing one of a variable's two items.
The two choice items for every in-range variable.
def variableItems (variableCount : Nat) : Finset SubsetSumItem :=
(Finset.range variableCount).image (fun index => .choice index false) ∪
(Finset.range variableCount).image (fun index => .choice index true)Three unit slack copies for every clause.
def slackItems (clauseCount : Nat) : Finset SubsetSumItem :=
((Finset.range clauseCount).product (Finset.range 3)).image
(fun pair => .slack pair.1 pair.2)All candidate items generated from a CNF formula.
def reductionItems (formula : CNF) : Finset SubsetSumItem :=
variableItems (reductionVariableCount formula) ∪ slackItems formula.length@[simp] theorem variable_mem_variableItems_iff
(variableCount index : Nat) (truth : Bool) :
.choice index truth ∈ variableItems variableCount ↔ index < variableCount := by
cases truth <;> simp [variableItems]@[simp] theorem slack_mem_slackItems_iff
(clauseCount clause slot : Nat) :
.slack clause slot ∈ slackItems clauseCount ↔
clause < clauseCount ∧ slot < 3 := by
simp [slackItems]@[simp] theorem choice_not_mem_slackItems
(clauseCount index : Nat) (truth : Bool) :
.choice index truth ∉ slackItems clauseCount := by
simp [slackItems]@[simp] theorem slack_not_mem_variableItems
(variableCount clause slot : Nat) :
.slack clause slot ∉ variableItems variableCount := by
simp [variableItems]theorem mem_reductionItems_iff {formula : CNF} {item : SubsetSumItem} :
item ∈ reductionItems formula ↔
(∃ index truth, item = .choice index truth ∧
index < reductionVariableCount formula) ∨
(∃ clause slot, item = .slack clause slot ∧
clause < formula.length ∧ slot < 3) := by
cases item with
| choice index truth =>
simp [reductionItems]
| slack clause slot =>
simp [reductionItems]Number of decimal columns in the constructed instance.
def reductionWidth (formula : CNF) : Nat :=
reductionVariableCount formula + formula.lengthWidth of one binary column block. The three spare bits make the power-of-two radix larger than every possible selected column sum.
def reductionBlockWidth (formula : CNF) : Nat :=
(reductionItems formula).card + 3A carry-free power-of-two radix. Choosing a binary radix keeps the textbook column construction directly serializable as fixed-width bit blocks, without requiring a general multiplication routine in the reduction machine.
def reductionBase (formula : CNF) : Nat :=
2 ^ reductionBlockWidth formulaThe digit contributed by one generated item to one column.
def itemDigit (formula : CNF) (item : SubsetSumItem) (column : Nat) : Nat :=
match item with
| .choice index truth =>
if column < reductionVariableCount formula then
if column = index then 1 else 0
else
(formula.getD (column - reductionVariableCount formula) []).count
(itemLiteral index truth)
| .slack clause _ =>
if column < reductionVariableCount formula then 0
else if column - reductionVariableCount formula = clause then 1 else 0Target digit: one in every variable column and four in every clause column.
def targetDigit (formula : CNF) (column : Nat) : Nat :=
if column < reductionVariableCount formula then 1 else 4Natural-number value assigned to a generated item.
def itemValue (formula : CNF) (item : SubsetSumItem) : Nat :=
packColumns (reductionBase formula) (reductionWidth formula)
(itemDigit formula item)The packed target natural number.
def reductionTarget (formula : CNF) : Nat :=
packColumns (reductionBase formula) (reductionWidth formula)
(targetDigit formula)The finite indexed SUBSET-SUM instance produced from a CNF formula.
def cnfToSubsetSum (formula : CNF) : SubsetSumInstance where
items := reductionItems formula
value := itemValue formula
target := reductionTarget formula@[simp] theorem itemDigit_variable_column
(formula : CNF) {index column : Nat} (truth : Bool)
(hcolumn : column < reductionVariableCount formula) :
itemDigit formula (.choice index truth) column =
if column = index then 1 else 0 := by
simp [itemDigit, hcolumn]@[simp] theorem itemDigit_slack_variable_column
(formula : CNF) {clause slot column : Nat}
(hcolumn : column < reductionVariableCount formula) :
itemDigit formula (.slack clause slot) column = 0 := by
simp [itemDigit, hcolumn]@[simp] theorem itemDigit_variable_clause_column
(formula : CNF) {index clause : Nat} (truth : Bool) :
itemDigit formula (.choice index truth)
(reductionVariableCount formula + clause) =
(formula.getD clause []).count (itemLiteral index truth) := by
simp [itemDigit]@[simp] theorem itemDigit_slack_clause_column
(formula : CNF) {sourceClause slot clause : Nat} :
itemDigit formula (.slack sourceClause slot)
(reductionVariableCount formula + clause) =
if clause = sourceClause then 1 else 0 := by
simp [itemDigit]@[simp] theorem targetDigit_variable_column
(formula : CNF) {column : Nat}
(hcolumn : column < reductionVariableCount formula) :
targetDigit formula column = 1 := by
simp [targetDigit, hcolumn]@[simp] theorem targetDigit_clause_column
(formula : CNF) (clause : Nat) :
targetDigit formula (reductionVariableCount formula + clause) = 4 := by
simp [targetDigit]end CLRS.Chapter34.SubsetSumReduction