Imports
Fixed delimiter maps over unary-frame streams
Affine runtime sources naturally emit every unary value with an ordinary
separator. Higher Cook--Levin controllers sometimes use frameEnd at a
fixed field position. This module supplies the reusable finite-state bridge:
ordinary separators are replaced cyclically by a nonempty delimiter table,
while ticks and pre-existing frame ends are preserved.
noncomputable sectionopen StateTransitionnamespace CLRS.Chapter34.Turing.PolyBuilderAdvance one position in a nonempty finite delimiter table.
def unaryFrameDelimiterNext (delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) (index : Fin delimiters.length) :
Fin delimiters.length :=
if hnext : index.val + 1 < delimiters.length then
⟨index.val + 1, hnext⟩
else
⟨0, hnonempty⟩One transducer action. Only ordinary separators advance the table.
def unaryFrameDelimiterStep (delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) (index : Fin delimiters.length)
(symbol : UnaryFrameSym) : UnaryFrameSym × Fin delimiters.length :=
match symbol with
| .tick => (.tick, index)
| .separator =>
(delimiters.get index,
unaryFrameDelimiterNext delimiters hnonempty index)
| .frameEnd => (.frameEnd, index)Pure streaming semantics from an arbitrary current table position.
def rewriteUnaryFrameDelimitersFrom (delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) :
Fin delimiters.length → List UnaryFrameSym → List UnaryFrameSym
| _, [] => []
| index, symbol :: rest =>
let action := unaryFrameDelimiterStep delimiters hnonempty index symbol
action.1 ::
rewriteUnaryFrameDelimitersFrom delimiters hnonempty action.2 restReplace ordinary separators cyclically from the first table entry.
def rewriteUnaryFrameDelimiters (delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) (input : List UnaryFrameSym) :
List UnaryFrameSym :=
rewriteUnaryFrameDelimitersFrom delimiters hnonempty ⟨0, hnonempty⟩ inputValue-level view of the same cyclic delimiter convention.
def encodeUnaryFrameWithDelimiterCycleFrom
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) :
Fin delimiters.length → List Nat → List UnaryFrameSym
| _, [] => []
| index, value :: rest =>
List.replicate value .tick ++ [delimiters.get index] ++
encodeUnaryFrameWithDelimiterCycleFrom delimiters hnonempty
(unaryFrameDelimiterNext delimiters hnonempty index) restUnary values encoded with the delimiter table starting at position zero.
def encodeUnaryFrameWithDelimiterCycle
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) (values : List Nat) :
List UnaryFrameSym :=
encodeUnaryFrameWithDelimiterCycleFrom delimiters hnonempty
⟨0, hnonempty⟩ valuesprivate theorem rewriteUnaryFrameDelimitersFrom_ticks
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length)
(index : Fin delimiters.length) (count : Nat)
(tail : List UnaryFrameSym) :
rewriteUnaryFrameDelimitersFrom delimiters hnonempty index
(List.replicate count .tick ++ tail) =
List.replicate count .tick ++
rewriteUnaryFrameDelimitersFrom delimiters hnonempty index tail := by
induction count with
| zero => rfl
| succ count ih =>
simp only [List.replicate_succ, List.cons_append,
rewriteUnaryFrameDelimitersFrom, unaryFrameDelimiterStep]
exact congrArg (List.cons .tick) ihThe symbol transducer has the expected value-level semantics on every well-formed ordinary unary frame.
theorem rewriteUnaryFrameDelimitersFrom_encodeUnaryFrame
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length)
(index : Fin delimiters.length) (values : List Nat) :
rewriteUnaryFrameDelimitersFrom delimiters hnonempty index
(encodeUnaryFrame values) =
encodeUnaryFrameWithDelimiterCycleFrom delimiters hnonempty index
values := by
induction values generalizing index with
| nil => rfl
| cons value rest ih =>
rw [show encodeUnaryFrame (value :: rest) =
List.replicate value .tick ++
.separator :: encodeUnaryFrame rest by
simp [encodeUnaryFrame, encodeUnaryFrameBlock, List.append_assoc]]
rw [show encodeUnaryFrameWithDelimiterCycleFrom delimiters hnonempty
index (value :: rest) =
List.replicate value .tick ++ [delimiters.get index] ++
encodeUnaryFrameWithDelimiterCycleFrom delimiters hnonempty
(unaryFrameDelimiterNext delimiters hnonempty index) rest by
rfl]
rw [rewriteUnaryFrameDelimitersFrom_ticks]
simp only [rewriteUnaryFrameDelimitersFrom,
unaryFrameDelimiterStep]
rw [ih]
simp only [List.append_assoc, List.singleton_append]Rewriting a complete ordinary unary frame is exactly cyclic encoding.
theorem rewriteUnaryFrameDelimiters_encodeUnaryFrame
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) (values : List Nat) :
rewriteUnaryFrameDelimiters delimiters hnonempty
(encodeUnaryFrame values) =
encodeUnaryFrameWithDelimiterCycle delimiters hnonempty values := by
exact rewriteUnaryFrameDelimitersFrom_encodeUnaryFrame delimiters
hnonempty ⟨0, hnonempty⟩ valuesFinite control records the current delimiter and a just-popped symbol.
inductive UnaryFrameDelimiterMapLabel (delimiters : List UnaryFrameSym)
| scan (index : Fin delimiters.length)
| emit (index : Fin delimiters.length) (symbol : UnaryFrameSym)
| finish
deriving DecidableEq, FintypeThe fixed prepend-output transducer.
def unaryFrameDelimiterMapRevProgram (delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) :
Program UnaryFrameSym UnaryFrameSym where
Label := UnaryFrameDelimiterMapLabel delimiters
main := .scan ⟨0, hnonempty⟩
op
| .scan index => .popInput .finish (.emit index)
| .emit index symbol =>
let action := unaryFrameDelimiterStep delimiters hnonempty index symbol
.pushOutput action.1 (.scan action.2)
| .finish => .haltprivate def unaryFrameDelimiterMapCfg
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length)
(label : UnaryFrameDelimiterMapLabel delimiters)
(buffer : Option UnaryFrameSym) (input output : List UnaryFrameSym) :
BuilderCfg (unaryFrameDelimiterMapRevProgram delimiters hnonempty) :=
{ label := some label
buffer₁ := buffer
buffer₂ := none
test := false
input := input
output := output
work₁ := []
work₂ := []
counter₁ := []
counter₂ := []
counter₃ := [] }private def unaryFrameDelimiterMapLoopCfg
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length)
(index : Fin delimiters.length) (buffer : Option UnaryFrameSym)
(input output : List UnaryFrameSym) :
BuilderCfg (unaryFrameDelimiterMapRevProgram delimiters hnonempty) :=
unaryFrameDelimiterMapCfg delimiters hnonempty (.scan index) buffer
input output
private theorem unaryFrameDelimiterMap_phase_eval
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length)
(index : Fin delimiters.length) (buffer : Option UnaryFrameSym)
(input output : List UnaryFrameSym) :
(flip Option.bind
(step (unaryFrameDelimiterMapRevProgram delimiters hnonempty)))^[
2 * input.length + 1]
(some (unaryFrameDelimiterMapLoopCfg delimiters hnonempty index
buffer input output)) =
some (unaryFrameDelimiterMapCfg delimiters hnonempty .finish none []
((rewriteUnaryFrameDelimitersFrom delimiters hnonempty index input).reverse ++
output)) := by
induction input generalizing index buffer output with
| nil => rfl
| cons symbol rest ih =>
rw [show 2 * (symbol :: rest).length + 1 =
(2 * rest.length + 1) + 1 + 1 by simp; omega,
Function.iterate_succ_apply, Function.iterate_succ_apply]
let action := unaryFrameDelimiterStep delimiters hnonempty index symbol
change
(flip Option.bind
(step (unaryFrameDelimiterMapRevProgram delimiters hnonempty)))^[
2 * rest.length + 1]
(some (unaryFrameDelimiterMapLoopCfg delimiters hnonempty action.2
(some symbol) rest (action.1 :: output))) = _
simpa [rewriteUnaryFrameDelimitersFrom, action, List.reverse_cons,
List.append_assoc] using
ih action.2 (some symbol) (action.1 :: output)Exact runtime, including the final empty pop and halt instruction.
def unaryFrameDelimiterMapSteps (input : List UnaryFrameSym) : Nat :=
2 * input.length + 2Exact reversed-output builder run.
def unaryFrameDelimiterMapRev_run (delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) (input : List UnaryFrameSym) :
EvalsToInTime
(step (unaryFrameDelimiterMapRevProgram delimiters hnonempty))
(initialCfg (unaryFrameDelimiterMapRevProgram delimiters hnonempty) input)
(some (haltCfg (unaryFrameDelimiterMapRevProgram delimiters hnonempty)
(rewriteUnaryFrameDelimiters delimiters hnonempty input).reverse))
(unaryFrameDelimiterMapSteps input) := by
let beforeHalt := unaryFrameDelimiterMapCfg delimiters hnonempty .finish none []
(rewriteUnaryFrameDelimiters delimiters hnonempty input).reverse
have hphase := unaryFrameDelimiterMap_phase_eval delimiters hnonempty
⟨0, hnonempty⟩ none input []
have hphaseRun : EvalsToInTime
(step (unaryFrameDelimiterMapRevProgram delimiters hnonempty))
(initialCfg (unaryFrameDelimiterMapRevProgram delimiters hnonempty) input)
(some beforeHalt) (2 * input.length + 1) := by
refine ⟨⟨2 * input.length + 1, ?_⟩, le_rfl⟩
simpa [beforeHalt, initialCfg, unaryFrameDelimiterMapLoopCfg,
unaryFrameDelimiterMapCfg, rewriteUnaryFrameDelimiters,
unaryFrameDelimiterMapRevProgram] using hphase
have hhalt : EvalsToInTime
(step (unaryFrameDelimiterMapRevProgram delimiters hnonempty))
beforeHalt
(some (haltCfg (unaryFrameDelimiterMapRevProgram delimiters hnonempty)
(rewriteUnaryFrameDelimiters delimiters hnonempty input).reverse)) 1 := by
refine ⟨⟨1, ?_⟩, le_rfl⟩
rfl
let full := EvalsToInTime.trans
(step (unaryFrameDelimiterMapRevProgram delimiters hnonempty))
(2 * input.length + 1) 1 _ beforeHalt _ hphaseRun hhalt
convert full using 1
simp [unaryFrameDelimiterMapSteps]
omegaExact compiled output contract for the reversed stream.
theorem unaryFrameDelimiterMapRev_outputs
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) :
Outputs (unaryFrameDelimiterMapRevProgram delimiters hnonempty)
(fun input =>
(rewriteUnaryFrameDelimiters delimiters hnonempty input).reverse)
unaryFrameDelimiterMapSteps :=
Outputs.of_builder_run fun input =>
⟨unaryFrameDelimiterMapRev_run delimiters hnonempty input⟩Linear polynomial envelope for the finite-state transducer.
noncomputable def unaryFrameDelimiterMap_polyBound :
PolyBound unaryFrameDelimiterMapSteps where
polynomial := 2 * Polynomial.X + 2
bound input := by
simp [unaryFrameDelimiterMapSteps, Polynomial.eval_add,
Polynomial.eval_mul, Polynomial.eval_X]Concrete polynomial-time TM2 for the prepend-order result.
noncomputable def unaryFrameDelimiterMapRev_computableInPolyTime
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) :
_root_.Turing.TM2ComputableInPolyTime id id
(fun input : List UnaryFrameSym =>
(rewriteUnaryFrameDelimiters delimiters hnonempty input).reverse) :=
ComputableInPolyTime
(unaryFrameDelimiterMapRevProgram delimiters hnonempty)
_ unaryFrameDelimiterMapSteps
(unaryFrameDelimiterMapRev_outputs delimiters hnonempty)
unaryFrameDelimiterMap_polyBoundConcrete polynomial-time TM2 for the forward rewritten stream.
noncomputable def unaryFrameDelimiterMap_computableInPolyTime
(delimiters : List UnaryFrameSym)
(hnonempty : 0 < delimiters.length) :
_root_.Turing.TM2ComputableInPolyTime id id
(rewriteUnaryFrameDelimiters delimiters hnonempty) := by
let composed :=
_root_.Turing.TM2Comp.TM2ComputableInPolyTime.comp_scratch
(unaryFrameDelimiterMapRev_computableInPolyTime delimiters hnonempty)
(reverse_computableInPolyTime (Γ := UnaryFrameSym))
simpa [Function.comp_def] using Classical.choice composedend CLRS.Chapter34.Turing.PolyBuilder