Cook--Levin whole-tableau validity family
This module serializes the verified one-row canonical-validity circuit across a finite family of already allocated public rows. It introduces neither boundary constraints nor a final conjunction.
namespace CLRS.Chapter34.Turing.CookLevinnoncomputable sectionPure gate-order trace of canonical-validity circuits serialized across a finite family of public tableau rows.
structure ValidCfgCircuitFamilyGateTrace (n : Nat) where
gates : List CircuitGate
outputs : Fin n → CircuitBuilder.WireAppend one exact single-row validity trace per row, in finite-index order.
def validCfgCircuitFamilyGateTrace
{tm : _root_.Turing.FinTM2} {H : Nat} (start : Nat) :
(n : Nat) → (rows : Fin n → CfgWires tm H) →
ValidCfgCircuitFamilyGateTrace n
| 0, _ =>
{ gates := []
outputs := fun row => Fin.elim0 row }
| n + 1, rows =>
let previous := validCfgCircuitFamilyGateTrace start n
(fun row => rows row.castSucc)
let last := canonicalValidityGateTrace
(start + previous.gates.length) (rows (Fin.last n))
{ gates := previous.gates ++ last.gates
outputs := fun row =>
if hrow : row.val < n then previous.outputs ⟨row.val, hrow⟩
else last.wire }A family trace pays the exact canonical row-validity cost once per row.
@[simp] theorem validCfgCircuitFamilyGateTrace_length
{tm : _root_.Turing.FinTM2} {H : Nat} (start n : Nat)
(rows : Fin n → CfgWires tm H) :
(validCfgCircuitFamilyGateTrace start n rows).gates.length =
n * validCfgGateCost tm H := by
induction n with
| zero => simp [validCfgCircuitFamilyGateTrace]
| succ n ih =>
simp only [validCfgCircuitFamilyGateTrace, List.length_append,
canonicalValidityGateTrace_length, ih]
ring
The recursive family trace is exactly the row-major flattening in which
row r starts after r copies of the fixed single-row validity cost.
theorem validCfgCircuitFamilyGateTrace_gates_eq_flatMap
{tm : _root_.Turing.FinTM2} {H : Nat} (start n : Nat)
(rows : Fin n → CfgWires tm H) :
(validCfgCircuitFamilyGateTrace start n rows).gates =
(List.ofFn fun row : Fin n =>
(canonicalValidityGateTrace
(start + row.val * validCfgGateCost tm H) (rows row)).gates).flatten := by
induction n with
| zero => rfl
| succ n ih =>
let prefixRows : Fin n → CfgWires tm H := fun row => rows row.castSucc
have hprefix := ih prefixRows
have hprefixLength :
(List.ofFn fun row : Fin n =>
(canonicalValidityGateTrace
(start + row.val * validCfgGateCost tm H)
(prefixRows row)).gates).flatten.length =
n * validCfgGateCost tm H := by
rw [← hprefix]
exact validCfgCircuitFamilyGateTrace_length start n prefixRows
simp only [validCfgCircuitFamilyGateTrace]
rw [hprefix]
rw [hprefixLength]
rw [List.ofFn_succ']
simp only [List.concat_eq_append, List.flatten_append,
List.flatten_singleton, Fin.val_last, Fin.val_castSucc, prefixRows]Proof-carrying result of serializing the canonical-validity circuit across an already allocated finite row family.
Builder after all row-validity circuits.
One canonical-validity output per public row.
The complete public-row prefix is preserved.
Every family output belongs to the final builder.
Exactly one local validity cost is paid per row.
Each output recognizes canonical evaluated row bits in the original builder, even after all later family members have been appended.
structure ValidCfgCircuitFamilyResult (tm : _root_.Turing.FinTM2) (H : Nat)
(base : CircuitBuilder) (n : Nat) (rows : Fin n → CfgWires tm H) where builder : CircuitBuilder outputs : Fin n → CircuitBuilder.Wire extension : base.Extends builder outputsValid : ∀ row, builder.WireValid (outputs row) gate_delta : builder.gates.length =
base.gates.length + n * validCfgGateCost tm H eval : ∀ inputs row,
builder.evalWire inputs (outputs row) = true ↔
(evalCfgBits base inputs (rows row)).Canonical
private def buildValidCfgCircuitFamily
{tm : _root_.Turing.FinTM2} {H : Nat} (base : CircuitBuilder) :
(n : Nat) → (rows : Fin n → CfgWires tm H) →
(∀ row, (rows row).ValidIn base) →
ValidCfgCircuitFamilyResult tm H base n rows
| 0, rows, _ =>
{ builder := base
outputs := fun row => Fin.elim0 row
extension := CircuitBuilder.Extends.refl base
outputsValid := fun row => Fin.elim0 row
gate_delta := by simp
eval := fun _ row => Fin.elim0 row }
| n + 1, rows, hrows => by
let prefixRows : Fin n → CfgWires tm H := fun row => rows row.castSucc
let previous := buildValidCfgCircuitFamily base n prefixRows
(fun row => hrows row.castSucc)
have hlast : (rows (Fin.last n)).ValidIn previous.builder :=
(hrows (Fin.last n)).mono previous.extension
let last := validCfgCircuit previous.builder (rows (Fin.last n)) hlast
let outputs : Fin (n + 1) → CircuitBuilder.Wire := fun row =>
if hrow : row.val < n then previous.outputs ⟨row.val, hrow⟩
else last.wire
refine
{ builder := last.builder
outputs := outputs
extension := previous.extension.trans last.extension
outputsValid := ?_
gate_delta := ?_
eval := ?_ }
· intro row
simp only [outputs]
split
next hrow =>
exact last.extension.wireValid
(previous.outputsValid ⟨row.val, hrow⟩)
next => exact last.valid
· rw [validCfgCircuit_gate_delta, previous.gate_delta]
ring
· intro inputs row
simp only [outputs]
split
next hrow =>
rw [last.extension.evalWire_eq inputs
(previous.outputsValid ⟨row.val, hrow⟩)]
rw [previous.eval]
have hindex : (⟨row.val, hrow⟩ : Fin n).castSucc = row := by
apply Fin.ext
rfl
simp only [prefixRows, hindex]
next hrow =>
have hlastRow : row = Fin.last n := by
apply Fin.ext
simp
omega
subst row
rw [validCfgCircuit_eval_iff, evalBundle_isSome_iff_canonical]
rw [evalCfgBits_extends previous.extension inputs
(rows (Fin.last n)) (hrows (Fin.last n))]Build one canonical-validity output for every public row, serially in row order.
def validCfgCircuitFamily
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base) :
ValidCfgCircuitFamilyResult tm H base n rows :=
buildValidCfgCircuitFamily base n rows hrows
private theorem buildValidCfgCircuitFamily_trace_eq
{tm : _root_.Turing.FinTM2} {H : Nat} (base : CircuitBuilder)
(n : Nat) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base) :
(buildValidCfgCircuitFamily base n rows hrows).builder.gates =
base.gates ++
(validCfgCircuitFamilyGateTrace base.gates.length n rows).gates ∧
∀ row, (buildValidCfgCircuitFamily base n rows hrows).outputs row =
(validCfgCircuitFamilyGateTrace base.gates.length n rows).outputs row := by
induction n with
| zero =>
simp [buildValidCfgCircuitFamily, validCfgCircuitFamilyGateTrace]
| succ n ih =>
let prefixRows : Fin n → CfgWires tm H := fun row => rows row.castSucc
let previous := buildValidCfgCircuitFamily base n prefixRows
(fun row => hrows row.castSucc)
let purePrevious := validCfgCircuitFamilyGateTrace base.gates.length
n prefixRows
rcases ih prefixRows (fun row => hrows row.castSucc) with
⟨hpreviousGates, hpreviousOutputs⟩
have hpreviousLength : previous.builder.gates.length =
base.gates.length + purePrevious.gates.length := by
rw [hpreviousGates]
simp only [List.length_append]
rfl
have hlast : (rows (Fin.last n)).ValidIn previous.builder :=
(hrows (Fin.last n)).mono previous.extension
let last := validCfgCircuit previous.builder (rows (Fin.last n)) hlast
let pureLast := canonicalValidityGateTrace
(base.gates.length + purePrevious.gates.length) (rows (Fin.last n))
have hlastGates : last.builder.gates =
previous.builder.gates ++ pureLast.gates := by
rw [validCfgCircuit_gates_eq]
simp only [pureLast, hpreviousLength]
have hlastWire : last.wire = pureLast.wire := by
rw [validCfgCircuit_wire_eq_trace]
simp only [pureLast, hpreviousLength]
simp only [buildValidCfgCircuitFamily,
validCfgCircuitFamilyGateTrace]
constructor
· rw [hlastGates, hpreviousGates]
simp only [prefixRows, purePrevious, pureLast, List.append_assoc]
· intro row
split
next hrow => exact hpreviousOutputs ⟨row.val, hrow⟩
next => exact hlastWireSerial row validation appends exactly the corresponding pure family trace.
theorem validCfgCircuitFamily_gates_eq
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base) :
(validCfgCircuitFamily base rows hrows).builder.gates =
base.gates ++
(validCfgCircuitFamilyGateTrace base.gates.length n rows).gates :=
(buildValidCfgCircuitFamily_trace_eq base n rows hrows).1Every row-validity output agrees with the corresponding family trace.
theorem validCfgCircuitFamily_output_eq_trace
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base) (row : Fin n) :
(validCfgCircuitFamily base rows hrows).outputs row =
(validCfgCircuitFamilyGateTrace base.gates.length n rows).outputs row :=
(buildValidCfgCircuitFamily_trace_eq base n rows hrows).2 rowSerial row validation preserves the original builder.
theorem validCfgCircuitFamily_extends
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base) :
base.Extends (validCfgCircuitFamily base rows hrows).builder :=
(validCfgCircuitFamily base rows hrows).extensionEvery serial row-validity output belongs to the common final builder.
theorem validCfgCircuitFamily_outputs_valid
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base) (row : Fin n) :
(validCfgCircuitFamily base rows hrows).builder.WireValid
((validCfgCircuitFamily base rows hrows).outputs row) :=
(validCfgCircuitFamily base rows hrows).outputsValid rowSerial row validation pays exactly the local validity cost once per row.
theorem validCfgCircuitFamily_gate_delta
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base) :
(validCfgCircuitFamily base rows hrows).builder.gates.length =
base.gates.length + n * validCfgGateCost tm H :=
(validCfgCircuitFamily base rows hrows).gate_deltaEvery old row has the same complete bit evaluation in the final family builder as in the original builder.
theorem validCfgCircuitFamily_evalCfgBits
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base)
(inputs : Nat → Bool) (row : Fin n) :
evalCfgBits (validCfgCircuitFamily base rows hrows).builder inputs (rows row) =
evalCfgBits base inputs (rows row) :=
evalCfgBits_extends (validCfgCircuitFamily base rows hrows).extension
inputs (rows row) (hrows row)Successful decoding of every old row is stable in the final family builder.
theorem validCfgCircuitFamily_evalBundle
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base)
(inputs : Nat → Bool) (row : Fin n) :
evalBundle (validCfgCircuitFamily base rows hrows).builder inputs (rows row)
((hrows row).mono (validCfgCircuitFamily base rows hrows).extension) =
evalBundle base inputs (rows row) (hrows row) :=
evalBundle_extends (validCfgCircuitFamily base rows hrows).extension
inputs (rows row) (hrows row)A row-family output is true exactly when that original public row decodes as a canonical machine configuration.
theorem validCfgCircuitFamily_eval_iff
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows : ∀ row, (rows row).ValidIn base)
(inputs : Nat → Bool) (row : Fin n) :
(validCfgCircuitFamily base rows hrows).builder.evalWire inputs
((validCfgCircuitFamily base rows hrows).outputs row) = true ↔
(evalBundle base inputs (rows row) (hrows row)).isSome = true := by
exact (validCfgCircuitFamily base rows hrows).eval inputs row |>.trans
(evalBundle_isSome_iff_canonical base inputs (rows row) (hrows row)).symmSerial row validation is independent of the supplied row-validity proof.
theorem validCfgCircuitFamily_proof_irrel
{tm : _root_.Turing.FinTM2} {H n : Nat}
(base : CircuitBuilder) (rows : Fin n → CfgWires tm H)
(hrows₁ hrows₂ : ∀ row, (rows row).ValidIn base) :
validCfgCircuitFamily base rows hrows₁ =
validCfgCircuitFamily base rows hrows₂ := by
congrendend CLRS.Chapter34.Turing.CookLevin