Affine sequential exactly-one traces
This file lifts the zero-based sequential exactly-one trace to an arbitrary gate start and a consecutive source-wire interval. The explicit arithmetic gate list is the specification consumed by the contextual concrete runner.
Main results:
-
affineSequentialExactlyOneGateStream_eq_trace: the public stream is the canonical semantic exactly-one encoding. -
affineSequentialExactlyOneGateList_eq_trace: the explicit arithmetic chunks are exactly the canonical semantic gate trace.
namespace CLRS.Chapter34.Turing.PolyBuilderopen CookLevin
Consecutive source wires beginning at rowBase.
def affineSequentialExactlyOneWires (rowBase count : Nat) : List Nat :=
(List.range count).map (fun wire => rowBase + wire)Exact forward encoding of an affine sequential exactly-one trace.
def affineSequentialExactlyOneGateStream
(start rowBase count : Nat) : List CircuitSym :=
(exactlyOneGateTrace start
(affineSequentialExactlyOneWires rowBase count)).gates.flatMap
encodeCircuitGateThe public affine stream is definitionally the semantic trace.
theorem affineSequentialExactlyOneGateStream_eq_trace
(start rowBase count : Nat) :
affineSequentialExactlyOneGateStream start rowBase count =
(exactlyOneGateTrace start
((List.range count).map (fun wire => rowBase + wire))).gates.flatMap
encodeCircuitGate := by
rflnamespace AffineExactlyOneFirst three-gate update from the two affine false seeds.
def firstChunk (start wire : Nat) : List CircuitGate :=
[.and start wire, .or (start + 1) (start + 2), .or start wire]
Later three-gate update after phase source wires have been scanned.
def laterChunk (start phase wire : Nat) : List CircuitGate :=
[.and (start + 3 * phase + 1) wire,
.or (start + 3 * phase) (start + 3 * phase + 2),
.or (start + 3 * phase + 1) wire]
Current seen-wire index after phase updates.
def seen (start phase : Nat) : Nat :=
if phase = 0 then start else start + 3 * phase + 1
Current duplicate-wire index after phase updates.
def duplicate (start phase : Nat) : Nat :=
if phase = 0 then start + 1 else start + 3 * phaseOne affine scan chunk, including the special first update.
def chunk (start phase wire : Nat) : List CircuitGate :=
if phase = 0 then firstChunk start wire else laterChunk start phase wire
Tail-first affine chunks for remaining consecutive source wires.
def chunksFrom (start rowBase : Nat) : Nat → Nat → List CircuitGate
| _, 0 => []
| phase, remaining + 1 =>
chunk start phase (rowBase + remaining) ++
chunksFrom start rowBase (phase + 1) remaining
private theorem arithmeticScanFrom_affineRange
(start rowBase phase remaining : Nat)
(scan : ExactlyOneArithmeticScan)
(hgates : scan.gates.length = 3 * phase + 2)
(hseen : scan.seen = seen start phase)
(hduplicate : scan.duplicate = duplicate start phase) :
let result := (affineSequentialExactlyOneWires rowBase remaining).reverse.foldl
(exactlyOneArithmeticStep start) scan
result.gates = scan.gates ++
chunksFrom start rowBase phase remaining ∧
result.gates.length = 3 * (phase + remaining) + 2 ∧
result.seen = seen start (phase + remaining) ∧
result.duplicate = duplicate start (phase + remaining) := by
induction remaining generalizing phase scan with
| zero =>
simp [affineSequentialExactlyOneWires, chunksFrom, hgates, hseen,
hduplicate]
| succ remaining ih =>
have hrange :
(affineSequentialExactlyOneWires rowBase (remaining + 1)).reverse =
(rowBase + remaining) ::
(affineSequentialExactlyOneWires rowBase remaining).reverse := by
simp [affineSequentialExactlyOneWires, List.range_succ,
List.reverse_append]
rw [hrange]
simp only [List.foldl]
let nextScan := exactlyOneArithmeticStep start scan (rowBase + remaining)
have hnextGates : nextScan.gates = scan.gates ++
chunk start phase (rowBase + remaining) := by
unfold nextScan exactlyOneArithmeticStep chunk
rw [hgates, hseen, hduplicate]
by_cases hphase : phase = 0
· subst phase
rfl
· simp only [hphase, ↓reduceIte, laterChunk, seen, duplicate]
simp [Nat.add_left_comm, Nat.add_comm]
have hnextLength : nextScan.gates.length =
3 * (phase + 1) + 2 := by
rw [hnextGates, List.length_append]
unfold chunk
by_cases hphase : phase = 0
· subst phase
have hg : scan.gates.length = 2 := by omega
simp [firstChunk, hg]
· simp [hphase, laterChunk, hgates]
omega
have hnextSeen : nextScan.seen = seen start (phase + 1) := by
unfold nextScan exactlyOneArithmeticStep seen
rw [hgates]
rw [if_neg (by omega : phase + 1 ≠ 0)]
change start + (3 * phase + 2) + 2 =
start + 3 * (phase + 1) + 1
omega
have hnextDuplicate :
nextScan.duplicate = duplicate start (phase + 1) := by
unfold nextScan exactlyOneArithmeticStep duplicate
rw [hgates]
rw [if_neg (by omega : phase + 1 ≠ 0)]
change start + (3 * phase + 2) + 1 = start + 3 * (phase + 1)
omega
rcases ih (phase + 1) nextScan hnextLength hnextSeen hnextDuplicate with
⟨hresultGates, hresultLength, hresultSeen, hresultDuplicate⟩
refine ⟨?_, ?_, ?_, ?_⟩
· rw [hresultGates, hnextGates]
simp [chunksFrom, List.append_assoc]
· simpa [Nat.add_assoc, Nat.add_left_comm, Nat.add_comm] using
hresultLength
· simpa [Nat.add_assoc, Nat.add_left_comm, Nat.add_comm] using
hresultSeen
· simpa [Nat.add_assoc, Nat.add_left_comm, Nat.add_comm] using
hresultDuplicateprivate theorem arithmeticScan_affineRange (start rowBase count : Nat) :
let scan := exactlyOneArithmeticScan start
(affineSequentialExactlyOneWires rowBase count)
scan.gates = [.const false, .const false] ++
chunksFrom start rowBase 0 count ∧
scan.gates.length = 3 * count + 2 ∧
scan.seen = seen start count ∧
scan.duplicate = duplicate start count := by
simpa [exactlyOneArithmeticScan, affineSequentialExactlyOneWires, seen,
duplicate] using
arithmeticScanFrom_affineRange start rowBase 0 count
({ gates := [.const false, .const false],
seen := start, duplicate := start + 1 } : ExactlyOneArithmeticScan)
rfl rfl rflExplicit arithmetic gate list for the complete affine constraint.
def gateList (start rowBase count : Nat) : List CircuitGate :=
[.const false, .const false] ++ chunksFrom start rowBase 0 count ++
[.not (duplicate start count),
.and (seen start count) (start + 3 * count + 2)]end AffineExactlyOneThe explicit affine chunks are exactly the semantic exactly-one trace.
theorem affineSequentialExactlyOneGateList_eq_trace
(start rowBase count : Nat) :
AffineExactlyOne.gateList start rowBase count =
(exactlyOneGateTrace start
(affineSequentialExactlyOneWires rowBase count)).gates := by
rw [exactlyOneGateTrace_gates_eq_arithmeticScan]
rcases AffineExactlyOne.arithmeticScan_affineRange start rowBase count with
⟨hgates, hlength, hseen, hduplicate⟩
simp only [AffineExactlyOne.gateList]
rw [hduplicate, hseen, hlength, hgates]
simp [Nat.add_assoc]end CLRS.Chapter34.Turing.PolyBuilder