Definitions bundle OAIQ037K013 of the split of OpenAI, The approximation threshold for metric k-median (result family 125)
DefinitionOAIQ037K013A definitions bundle of the split of OpenAI's proof of OAI.MetricKMedian.main_finite_work, carved from OpenAI's openai/math development (OpenAI, The approximation threshold for metric k-median (result family 125), OpenAI Math Release, September 24, 2026, result family 125, github.com/openai/math at commit adc7f12, Apache License 2.0) and ported to Lean 4.33.1 and Mathlib 0df444a. The declarations and their proofs are OpenAI's.
Contents. It holds 73 declarations of OpenAI's Lean: 37 definitions and 36 theorems. The definitions and types are OAI.MetricKMedian.Binary.Compose.code, OAI.MetricKMedian.Binary.Compose.machine, OAI.MetricKMedian.Binary.Compose.right, OAI.MetricKMedian.Binary.Compose.source, OAI.MetricKMedian.Binary.Compose.target, OAI.MetricKMedian.Binary.Compose.transfer, OAI.MetricKMedian.Binary.Compose.transferCfg, OAI.MetricKMedian.Binary.Embedding.cfg, OAI.MetricKMedian.Binary.Embedding.stmt, OAI.MetricKMedian.Binary.Machine.growth, OAI.MetricKMedian.Binary.ParallelTransducer.code, OAI.MetricKMedian.Binary.ParallelTransducer.emit, OAI.MetricKMedian.Binary.ParallelTransducer.emitPair, OAI.MetricKMedian.Binary.ParallelTransducer.input, OAI.MetricKMedian.Binary.ParallelTransducer.left, OAI.MetricKMedian.Binary.ParallelTransducer.leftCfg, OAI.MetricKMedian.Binary.ParallelTransducer.machine, OAI.MetricKMedian.Binary.ParallelTransducer.output, OAI.MetricKMedian.Binary.ParallelTransducer.readCfg, OAI.MetricKMedian.Binary.ParallelTransducer.right, OAI.MetricKMedian.Binary.ParallelTransducer.rightCfg, OAI.MetricKMedian.Binary.ParallelTransducer.store, OAI.MetricKMedian.Binary.ParallelTransducer.transfer, OAI.MetricKMedian.Binary.PolyProgram.comp, OAI.MetricKMedian.Binary.PolyProgram.compTime, OAI.MetricKMedian.Binary.PolyProgram.congr, OAI.MetricKMedian.Binary.PolyProgram.cons, OAI.MetricKMedian.Binary.PolyProgram.constant, OAI.MetricKMedian.Binary.PolyProgram.sizeBound, OAI.MetricKMedian.Binary.Thread.Key, OAI.MetricKMedian.Binary.Thread.Label, OAI.MetricKMedian.Binary.Thread.State, OAI.MetricKMedian.Binary.Thread.buffer, OAI.MetricKMedian.Binary.Thread.emitting, OAI.MetricKMedian.Binary.Thread.source, OAI.MetricKMedian.Binary.WordTransducer.constant, OAI.MetricKMedian.Binary.WordTransducer.prepend.
Sources. They come from these modules of lean/OAI/Combinatorics/KMedian, in whole or in part: KMedian_Binary_BooleanComposition, KMedian_Binary_BooleanEmbedding, KMedian_Binary_BooleanListPrimitives, KMedian_Binary_BooleanMachine, KMedian_Binary_BooleanParallelTransducer, KMedian_Binary_BooleanPolynomial, KMedian_Binary_BooleanProducts, KMedian_Binary_BooleanThread.
Imports. It imports the bundles OAIQ037K000 and OAIQ037K001 of this split.
Imported by (directly, in this split): the bundles OAIQ037K027 and OAIQ037K046.
import Mathlib
import Definitions.Def_OAIQ037K000
import Definitions.Def_OAIQ037K001
section
-- module Solutions.OAIQ037_KM.KMedian_Binary_BooleanMachine
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
section
namespace MetricKMedian.Binary
open Turing StateTransition Function Finset
attribute [instance] Machine.decK Machine.finK Machine.finLabel Machine.finState
namespace Trace
variable {α β : Type*} {f : α → Option α}
theorem map {g : β → Option β} (e : α → β)
(he : ∀ a b, f a=some b → g (e a)=some (e b))
{n : ℕ} {a b : α} (h : Trace f n a b) : Trace g n (e a) (e b) := by
induction h with
| refl => exact refl _
| cons hs _ ih => exact cons (he _ _ hs) ih
theorem of_iterate {n : ℕ} {a b : α}
(h : (flip bind f)^[n] (some a)=some b) : Trace f n a b := by
induction n generalizing a with
| zero =>
have hab : a=b := Option.some.inj h
subst b
exact refl a
| succ n ih =>
rw [Function.iterate_succ_apply] at h
cases hc : f a with
| none =>
have hz : ∀ t : ℕ, (flip bind f)^[t] (none : Option α)=none := by
intro t
induction t with
| zero => rfl
| succ t iht =>
rw [Function.iterate_succ_apply]
exact iht
change (flip bind f)^[n] (f a)=some b at h
rw [hc,hz] at h
contradiction
| some c =>
have hh : (flip bind f)^[n] (some c)=some b := by
change (flip bind f)^[n] (f a)=some b at h
rwa [hc] at h
exact cons hc (ih hh)
end Trace
namespace Machine
variable {K L S : Type} [DecidableEq K]
variable [Fintype K]
theorem volume_update (s : K → List Bool) (k : K) (v : List Bool) :
volume (update s k v)+(s k).length=volume s+v.length := by
classical
unfold volume
have he : (fun j => (update s k v j).length)=update (fun j => (s j).length) k v.length := by
funext j
simp only [update_apply]
split <;> rfl
rw [he,Finset.sum_update_of_mem (mem_univ k)]
have hh := Finset.sum_erase_add (univ : Finset K) (fun j => (s j).length) (mem_univ k)
simp only [Finset.sdiff_singleton_eq_erase]
omega
theorem stepAux_volume (q : TM2.Stmt (fun _ : K => Bool) L S)
(v : S) (s : K → List Bool) :
volume (TM2.stepAux q v s).stk ≤ volume s+pushes q := by
induction q generalizing v s with
| push k g q ih =>
have h := ih v (update s k (g v::s k))
have hv := volume_update s k (g v::s k)
simp only [List.length_cons] at hv
simpa only [TM2.stepAux,pushes,Nat.add_assoc] using (by omega :
volume (TM2.stepAux q v (update s k (g v::s k))).stk≤volume s+(1+pushes q))
| peek k g q ih => exact ih _ _
| pop k g q ih =>
have h := ih (g v (s k).head?) (update s k (s k).tail)
have hv := volume_update s k (s k).tail
have hl := List.length_tail (l := s k)
simp only [TM2.stepAux,pushes]
omega
| load g q ih => exact ih _ _
| branch g q r ihq ihr =>
cases hg : g v
· simpa only [TM2.stepAux,hg,Bool.false_eq_true,Bool.cond_false,pushes] using
(ihr v s).trans (Nat.add_le_add_left (le_max_right (pushes q) _) _)
· simpa only [TM2.stepAux,hg,Bool.cond_true,pushes] using
(ihq v s).trans (Nat.add_le_add_left (le_max_left _ (pushes r)) _)
| goto g => simp only [TM2.stepAux,pushes,Nat.add_zero,le_refl]
| halt => simp only [TM2.stepAux,pushes,Nat.add_zero,le_refl]
def growth (M : Machine) : ℕ := ∑ l, pushes (M.code l)
theorem step_volume (M : Machine) (a b : M.Cfg) (h : M.step a=some b) :
volume b.stk ≤ volume a.stk+M.growth := by
rcases a with ⟨l,v,s⟩
cases l with
| none => cases h
| some l =>
have hb : b=TM2.stepAux (M.code l) v s := (Option.some.inj h).symm
rw [hb]
exact (stepAux_volume _ _ _).trans (Nat.add_le_add_left
(show pushes (M.code l) ≤ M.growth from
single_le_sum (f:=fun x => pushes (M.code x)) (fun _ _ => Nat.zero_le _) (mem_univ l)) _)
theorem trace_volume (M : Machine) {n : ℕ} {a b : M.Cfg}
(h : Trace M.step n a b) : volume b.stk ≤ volume a.stk+n*M.growth := by
induction h with
| refl => simp
| @cons n a b c hab hbc ih =>
have hs := M.step_volume a b hab
calc
_ ≤ volume b.stk+n*M.growth := ih
_ ≤ volume a.stk+(n+1)*M.growth := by rw [Nat.add_mul]; omega
theorem output_length (M : Machine) {s t : List Bool} {n : ℕ}
(h : TM2OutputsInTime M.tm s (some t) n) : t.length ≤ s.length+n*M.growth := by
have ht : Trace M.step h.steps (M.initialCfg s) (M.finalCfg t) :=
Trace.of_iterate h.evals_in_steps
have hv := M.trace_volume ht
simp only [initial_volume,final_volume] at hv
exact hv.trans (Nat.add_le_add_left (Nat.mul_le_mul_right _ h.steps_le_m) _)
end Machine
end MetricKMedian.Binary
end
end OAI
end
section
-- module Solutions.OAIQ037_KM.KMedian_Binary_BooleanEmbedding
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
section
namespace MetricKMedian.Binary
open Turing Function
namespace Embedding
variable {K L S K' L' S' : Type} [DecidableEq K] [DecidableEq K']
variable (E : Embedding K L S K' L' S')
def stmt : TM2.Stmt (fun _ : K => Bool) L S → TM2.Stmt (fun _ : K' => Bool) L' S'
| .push k f q => .push (E.key k) (fun v => f (E.read v)) (stmt q)
| .peek k f q => .peek (E.key k) (fun v x => E.write v (f (E.read v) x)) (stmt q)
| .pop k f q => .pop (E.key k) (fun v x => E.write v (f (E.read v) x)) (stmt q)
| .load f q => .load (fun v => E.write v (f (E.read v))) (stmt q)
| .branch f q r => .branch (fun v => f (E.read v)) (stmt q) (stmt r)
| .goto f => .goto (fun v => E.label (f (E.read v)))
| .halt => E.stop
def cfg (a : TM2.Cfg (fun _ : K => Bool) L S) : TM2.Cfg (fun _ : K' => Bool) L' S' :=
⟨a.l.elim E.halted (fun l => some (E.label l)),E.state a.var,E.stack a.stk⟩
theorem stepAux_stmt (q : TM2.Stmt (fun _ : K => Bool) L S) (v : S) (s : K → List Bool) :
TM2.stepAux (E.stmt q) (E.state v) (E.stack s)=E.cfg (TM2.stepAux q v s) := by
induction q generalizing v s with
| push k f q ih =>
simp only [stmt,TM2.stepAux,E.read_state,E.stack_key,← E.stack_update]
exact ih _ _
| peek k f q ih =>
simp only [stmt,TM2.stepAux,E.read_state,E.stack_key,E.write_state]
exact ih _ _
| pop k f q ih =>
simp only [stmt,TM2.stepAux,E.read_state,E.stack_key,E.write_state,← E.stack_update]
exact ih _ _
| load f q ih =>
simp only [stmt,TM2.stepAux,E.read_state,E.write_state]
exact ih _ _
| branch f q r ihq ihr =>
cases h : f v <;> simp only [stmt,TM2.stepAux,E.read_state,h,Bool.cond_false,Bool.cond_true]
· exact ihr _ _
· exact ihq _ _
| goto f => simp only [stmt,TM2.stepAux,E.read_state,cfg,Option.elim_some]
| halt => exact E.stop_spec v s
theorem step_cfg (m : L → TM2.Stmt (fun _ : K => Bool) L S)
(m' : L' → TM2.Stmt (fun _ : K' => Bool) L' S')
(hm : ∀ l, m' (E.label l)=E.stmt (m l))
(a b : TM2.Cfg (fun _ : K => Bool) L S) (h : TM2.step m a=some b) :
TM2.step m' (E.cfg a)=some (E.cfg b) := by
rcases a with ⟨l,v,s⟩
cases l with
| none => cases h
| some l =>
have hb : b=TM2.stepAux (m l) v s := (Option.some.inj h).symm
subst b
simp only [cfg,Option.elim_some,TM2.step,hm]
exact congrArg some (E.stepAux_stmt (m l) v s)
theorem trace (m : L → TM2.Stmt (fun _ : K => Bool) L S)
(m' : L' → TM2.Stmt (fun _ : K' => Bool) L' S')
(hm : ∀ l, m' (E.label l)=E.stmt (m l))
{n : ℕ} {a b : TM2.Cfg (fun _ : K => Bool) L S} (h : Trace (TM2.step m) n a b) :
Trace (TM2.step m') n (E.cfg a) (E.cfg b) :=
h.map E.cfg (E.step_cfg m m' hm)
end Embedding
end MetricKMedian.Binary
end
end OAI
end
section
-- module Solutions.OAIQ037_KM.KMedian_Binary_BooleanComposition
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
section
namespace MetricKMedian.Binary
open Turing Function
namespace Compose
variable (M N : Machine)
def right : Embedding N.K N.Label N.State (Key M N) (Label M N) (State M N) where
key k := .inr (.inr k)
read v := v.2.1
write v x := (v.1,x,v.2.2)
state v := (M.initial,v,none)
read_state _ := rfl
write_state _ _ := rfl
stack s := Sum.elim (fun _ => []) (Sum.elim (fun _ => []) s)
stack_key _ _ := rfl
stack_update s k x := by
funext j
rcases j with j | j
· simp only [update_apply,Sum.elim_inl,Sum.inl_ne_inr,ite_false]
· rcases j with j | j <;> simp only [update_apply,Sum.elim_inl,Sum.elim_inr,Sum.inr.injEq,Sum.inl_ne_inr,ite_false]
label l := .inr (.inr l)
halted := none
stop := .halt
stop_spec _ _ := rfl
def source (b : Bool) : Key M N := if b then auxiliary M N else .inl M.output
def target (b : Bool) : Key M N := if b then .inr (.inr N.input) else auxiliary M N
theorem source_ne_target (b : Bool) : source M N b ≠ target M N b := by
cases b <;> simp [source,target,auxiliary]
def transfer (b : Bool) : TM2.Stmt (fun _ : Key M N => Bool) (Label M N) (State M N) :=
.pop (source M N b) (fun v c => (v.1,v.2.1,c))
(.branch (fun v => v.2.2.isSome)
(.push (target M N b) (fun v => v.2.2.getD false)
(.load (clean M N) (.goto (fun _ => phaseLabel M N b))))
(.load (clean M N) (.goto (fun _ => following M N b))))
def code : Label M N → TM2.Stmt (fun _ : Key M N => Bool) (Label M N) (State M N)
| .inl l => (left M N).stmt (M.code l)
| .inr (.inl b) => transfer M N b
| .inr (.inr l) => (right M N).stmt (N.code l)
abbrev machine : Machine where
K := Key M N
input := .inl M.input
output := .inr (.inr N.output)
Label := Label M N
main := .inl M.main
State := State M N
initial := (M.initial,N.initial,none)
code := code M N
theorem code_left (l : M.Label) : (machine M N).code ((left M N).label l)=
(left M N).stmt (M.code l) := rfl
theorem code_right (l : N.Label) : (machine M N).code ((right M N).label l)=
(right M N).stmt (N.code l) := rfl
theorem initial_left (s : List Bool) : (left M N).cfg (M.initialCfg s)=
(machine M N).initialCfg s := by
apply cfg_ext <;> try rfl
funext k
rcases k with k | k <;> simp [Embedding.cfg,left,Machine.initialCfg,machine]
theorem final_right (s : List Bool) : (right M N).cfg (N.finalCfg s)=
(machine M N).finalCfg s := by
apply cfg_ext <;> try rfl
funext k
rcases k with k | k
· simp [Embedding.cfg,right,Machine.finalCfg,machine]
· rcases k with k | k <;> simp [Embedding.cfg,right,Machine.finalCfg,machine]
end Compose
namespace Compose
variable (M N : Machine)
def transferCfg (b : Bool) (xs ys : List Bool) : (machine M N).Cfg :=
⟨some (phaseLabel M N b), (M.initial,N.initial,none),
twoStacks (source M N b) (target M N b) xs ys⟩
theorem transfer_cons (b x : Bool) (xs ys : List Bool) :
(machine M N).step (transferCfg M N b (x::xs) ys)=
some (transferCfg M N b xs (x::ys)) := by
change some (TM2.stepAux (transfer M N b) (M.initial,N.initial,none)
(twoStacks (source M N b) (target M N b) (x::xs) ys))=some (transferCfg M N b xs (x::ys))
simp only [transfer,TM2.stepAux]
rw [twoStacks_source]
simp only [List.head?_cons,List.tail_cons,Option.isSome_some,Bool.cond_true,Option.getD_some,clean]
rw [update_of_ne (Ne.symm (source_ne_target M N b)),twoStacks_target (source_ne_target M N b)]
rw [twoStacks_move (source_ne_target M N b)]
rfl
theorem transfer_run (b : Bool) (xs ys : List Bool) :
Trace (machine M N).step xs.length (transferCfg M N b xs ys)
(transferCfg M N b [] (xs.reverse++ys)) := by
induction xs generalizing ys with
| nil => exact Trace.refl _
| cons x xs ih =>
have h := Trace.cons (transfer_cons M N b x xs ys) (ih (x::ys))
simpa only [List.length_cons,List.reverse_cons,List.append_assoc,List.singleton_append] using h
theorem transfer_empty (b : Bool) (ys : List Bool) :
(machine M N).step (transferCfg M N b [] ys)=
some ⟨some (following M N b),(M.initial,N.initial,none),
twoStacks (source M N b) (target M N b) [] ys⟩ := by
change some (TM2.stepAux (transfer M N b) (M.initial,N.initial,none)
(twoStacks (source M N b) (target M N b) [] ys))=_
simp only [transfer,TM2.stepAux]
rw [twoStacks_source]
simp only [List.head?_nil,List.tail_nil,Option.isSome_none,Bool.cond_false,clean,twoStacks_pop_empty]
theorem left_final_transfer (xs : List Bool) :
(left M N).cfg (M.finalCfg xs)=transferCfg M N false xs [] := by
apply cfg_ext <;> try rfl
funext k
rcases k with k | k
· simp [Embedding.cfg,left,Machine.finalCfg,transferCfg,twoStacks,source,target,auxiliary,Sum.inl.injEq,Sum.inl_ne_inr]
· rcases k with k | k <;>
simp [Embedding.cfg,left,Machine.finalCfg,transferCfg,twoStacks,source,target,auxiliary,Sum.inr.injEq,Sum.inr_ne_inl]
theorem transfer_change (ys : List Bool) :
(machine M N).step (transferCfg M N false [] ys)=some (transferCfg M N true ys []) := by
rw [transfer_empty]
apply congrArg some
apply cfg_ext <;> try rfl
funext k
rcases k with k | k
· simp [transferCfg,source,target,twoStacks,auxiliary,Sum.inl.injEq,Sum.inl_ne_inr]
· rcases k with k | k <;> simp [transferCfg,source,target,twoStacks,auxiliary,Sum.inr.injEq,Sum.inr_ne_inl]
theorem transfer_end (ys : List Bool) :
(machine M N).step (transferCfg M N true [] ys)=some ((right M N).cfg (N.initialCfg ys)) := by
rw [transfer_empty]
apply congrArg some
apply cfg_ext <;> try rfl
funext k
rcases k with k | k
· simp [Embedding.cfg,right,Machine.initialCfg,source,target,twoStacks,auxiliary,Sum.inl_ne_inr]
· rcases k with k | k <;>
simp [Embedding.cfg,right,Machine.initialCfg,source,target,twoStacks,auxiliary,Sum.inr.injEq,Sum.inr_ne_inl]
theorem transfer_full (xs : List Bool) :
Trace (machine M N).step (2*xs.length+2)
((left M N).cfg (M.finalCfg xs)) ((right M N).cfg (N.initialCfg xs)) := by
rw [left_final_transfer]
have h₁ := transfer_run M N false xs []
simp only [List.append_nil] at h₁
have h₂ := Trace.cons (transfer_change M N xs.reverse) (transfer_run M N true xs.reverse [])
simp only [List.length_reverse,List.reverse_reverse,List.append_nil] at h₂
have h₃ := Trace.cons (transfer_end M N xs) (Trace.refl _)
have hh := (h₁.trans h₂).trans h₃
simpa only [show xs.length+(xs.length+1)+(0+1)=2*xs.length+2 by omega] using hh
theorem run {s t u : List Bool} {n m : ℕ}
(hM : Trace M.step n (M.initialCfg s) (M.finalCfg t))
(hN : Trace N.step m (N.initialCfg t) (N.finalCfg u)) :
Trace (machine M N).step (n+2*t.length+2+m)
((machine M N).initialCfg s) ((machine M N).finalCfg u) := by
have h₁ := (left M N).trace M.code (machine M N).code (code_left M N) hM
have h₂ := (right M N).trace N.code (machine M N).code (code_right M N) hN
rw [initial_left] at h₁
rw [final_right] at h₂
have hh := (h₁.trans (transfer_full M N t)).trans h₂
simpa only [Machine.step,machine,Nat.add_assoc] using hh
end Compose
end MetricKMedian.Binary
end
end OAI
end
section
-- module Solutions.OAIQ037_KM.KMedian_Binary_BooleanPolynomial
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
section
namespace MetricKMedian.Binary
open Turing Polynomial
namespace PolyProgram
variable {α β γ : Type} {ea : α → List Bool} {eb : β → List Bool} {ec : γ → List Bool}
variable {f : α → β} {g : β → γ}
noncomputable def sizeBound (P : PolyProgram ea eb f) : Polynomial ℕ :=
X+P.time*C P.machine.growth
theorem length_bound (P : PolyProgram ea eb f) (a : α) :
(eb (f a)).length ≤ P.sizeBound.eval (ea a).length := by
simpa only [sizeBound,Polynomial.eval_add,Polynomial.eval_X,Polynomial.eval_mul,Polynomial.eval_C]
using P.machine.output_length (P.outputs a)
noncomputable def compTime (P : PolyProgram ea eb f) (Q : PolyProgram eb ec g) : Polynomial ℕ :=
P.time+2*P.sizeBound+2+Q.time.comp P.sizeBound
noncomputable def comp (P : PolyProgram ea eb f) (Q : PolyProgram eb ec g) : PolyProgram ea ec (g ∘ f) where
machine := Compose.machine P.machine Q.machine
time := P.compTime Q
outputs a := by
let hP := P.outputs a
let hQ := Q.outputs (f a)
have tP : Trace P.machine.step hP.steps (P.machine.initialCfg (ea a))
(P.machine.finalCfg (eb (f a))) := Trace.of_iterate hP.evals_in_steps
have tQ : Trace Q.machine.step hQ.steps (Q.machine.initialCfg (eb (f a)))
(Q.machine.finalCfg (ec (g (f a)))) := Trace.of_iterate hQ.evals_in_steps
have h := Compose.run P.machine Q.machine tP tQ
refine ⟨⟨_,h.iterate_eq⟩,?_⟩
have hl := P.length_bound a
have hqp := (hQ.steps_le_m).trans (polynomial_eval_mono Q.time hl)
have hpp := hP.steps_le_m
simp only [compTime,Polynomial.eval_add,Polynomial.eval_mul,Polynomial.eval_ofNat,
Polynomial.eval_comp]
omega
def congr (P : PolyProgram ea eb f) (f' : α → β) (h : ∀ a, f a=f' a) : PolyProgram ea eb f' where
machine := P.machine
time := P.time
outputs a := by rw [← h a]; exact P.outputs a
end PolyProgram
end MetricKMedian.Binary
end
end OAI
end
section
-- module Solutions.OAIQ037_KM.KMedian_Binary_BooleanParallelTransducer
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
section
namespace MetricKMedian.Binary
open Turing Function Polynomial Finset
attribute [instance] ParallelTransducer.finiteQ
namespace ParallelTransducer
variable (T : ParallelTransducer)
abbrev input : Key := 0
abbrev left : Key := 1
abbrev right : Key := 2
abbrev output : Key := 3
def store (xs ls rs ys : List Bool) : Key → List Bool :=
fun k => if k=input then xs else if k=left then ls else if k=right then rs else ys
theorem store_update_input (xs ls rs ys zs : List Bool) :
update (store xs ls rs ys) input zs=store zs ls rs ys := by
funext k
fin_cases k <;> simp [store,input,left,right]
theorem store_update_left (xs ls rs ys zs : List Bool) :
update (store xs ls rs ys) left zs=store xs zs rs ys := by
funext k
fin_cases k <;> simp [store,input,left,right]
theorem store_update_right (xs ls rs ys zs : List Bool) :
update (store xs ls rs ys) right zs=store xs ls zs ys := by
funext k
fin_cases k <;> simp [store,input,left,right]
theorem store_update_output (xs ls rs ys zs : List Bool) :
update (store xs ls rs ys) output zs=store xs ls rs zs := by
funext k
fin_cases k <;> simp [store,input,left,right,output]
def emit (k : Key) : List Bool → TM2.Stmt (fun _ : Key => Bool) (Label T) State →
TM2.Stmt (fun _ : Key => Bool) (Label T) State
| [], s => s
| b::bs, s => .push k (fun _ => b) (emit k bs s)
theorem emit_step (k : Key) (bits : List Bool) (s : TM2.Stmt (fun _ : Key => Bool) (Label T) State)
(v : State) (stk : Key → List Bool) :
TM2.stepAux (emit T k bits s) v stk=TM2.stepAux s v (update stk k (bits.reverse++stk k)) := by
induction bits generalizing stk with
| nil => simp only [emit,List.reverse_nil,List.nil_append,update_eq_self]
| cons b bs ih =>
simp only [emit,TM2.stepAux,ih,update_self,update_idem,List.reverse_cons,
List.append_assoc,List.singleton_append]
def emitPair (p : List Bool × List Bool) (s : TM2.Stmt (fun _ : Key => Bool) (Label T) State) :=
emit T left p.1 (emit T right p.2 s)
theorem emitPair_step (p : List Bool × List Bool) (s : TM2.Stmt (fun _ : Key => Bool) (Label T) State)
(v : State) (xs ls rs ys : List Bool) :
TM2.stepAux (emitPair T p s) v (store xs ls rs ys)=
TM2.stepAux s v (store xs (p.1.reverse++ls) (p.2.reverse++rs) ys) := by
simp [emitPair,emit_step,store,input,left,right,store_update_left,store_update_right]
def transfer (phase : Bool) : TM2.Stmt (fun _ : Key => Bool) (Label T) State :=
.pop (if phase then left else right) (fun _ b => b)
(.branch Option.isSome
(.push output (fun b => b.getD false) (.load (fun _ => none) (.goto (fun _ => .inr phase))))
(.load (fun _ => none) (if phase then .halt else .goto (fun _ => .inr true))))
def code : Label T → TM2.Stmt (fun _ : Key => Bool) (Label T) State
| .inl q => .pop input (fun _ b => b)
(.branch Option.isSome
(.branch (fun b => b.getD false)
(.load (fun _ => none) (emitPair T (T.next q true).2 (.goto (fun _ => .inl (T.next q true).1))))
(.load (fun _ => none) (emitPair T (T.next q false).2 (.goto (fun _ => .inl (T.next q false).1)))))
(.load (fun _ => none) (emitPair T (T.finish q) (.goto (fun _ => .inr false)))))
| .inr b => transfer T b
abbrev machine : Machine where
K := Key
input := input
output := output
Label := Label T
main := .inl T.initial
State := State
initial := none
code := code T
def readCfg (q : T.Q) (xs ls rs : List Bool) : (machine T).Cfg :=
⟨some (.inl q),none,store xs ls rs []⟩
def rightCfg (ls rs ys : List Bool) : (machine T).Cfg :=
⟨some (.inr false),none,store [] ls rs ys⟩
def leftCfg (ls ys : List Bool) : (machine T).Cfg :=
⟨some (.inr true),none,store [] ls [] ys⟩
theorem left_cons (b : Bool) (ls ys : List Bool) :
(machine T).step (T.leftCfg (b::ls) ys)=some (T.leftCfg ls (b::ys)) := by
simp [leftCfg,TM2.step,code,transfer,TM2.stepAux,store,input,left,right,output,store_update_left,store_update_output]
theorem left_nil (ys : List Bool) :
(machine T).step (T.leftCfg [] ys)=some ((machine T).finalCfg ys) := by
apply congrArg some
apply cfg_ext
· rfl
· rfl
· funext k
fin_cases k <;> simp [Machine.finalCfg,code,transfer,TM2.stepAux,store,input,left,right,output]
theorem left_run (ls ys : List Bool) :
Trace (machine T).step (ls.length+1) (T.leftCfg ls ys) ((machine T).finalCfg (ls.reverse++ys)) := by
induction ls generalizing ys with
| nil => exact Trace.cons (T.left_nil ys) (Trace.refl _)
| cons b ls ih =>
simpa only [List.length_cons,List.reverse_cons,List.append_assoc,List.singleton_append] using
Trace.cons (T.left_cons b ls ys) (ih (b::ys))
end ParallelTransducer
end MetricKMedian.Binary
end
end OAI
end
section
-- module Solutions.OAIQ037_KM.KMedian_Binary_BooleanThread
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
section
namespace MetricKMedian.Binary
open Turing Function Polynomial
namespace Thread
variable (M : Machine)
abbrev Key := M.K ⊕ Bool
abbrev Label := M.Label ⊕ Fin 4
abbrev State := M.State × Option Bool
abbrev source : Key M := .inr false
abbrev buffer : Key M := .inr true
abbrev emitting : Label M := .inr 2
end Thread
end MetricKMedian.Binary
end
end OAI
end
section
-- module Solutions.OAIQ037_KM.KMedian_Binary_BooleanProducts
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
section
namespace MetricKMedian.Binary
open Turing Function Polynomial
namespace WordTransducer
def constant (s : List Bool) : Transducer where
Q := Unit
initial := ()
next _ _ := ((),[])
finish _ := s
theorem constant_run (s xs : List Bool) : (constant s).run () xs=s := by
induction xs with
| nil => rfl
| cons b xs ih => exact ih
end WordTransducer
namespace PolyProgram
variable {α β γ δ : Type}
variable {ea : α → List Bool} {eb : β → List Bool} {ec : γ → List Bool} {ed : δ → List Bool}
variable {f : α → β} {g : γ → δ}
noncomputable def constant (ea : α → List Bool) (eb : β → List Bool) (b : β) :
PolyProgram ea eb (fun _ => b) :=
(WordTransducer.constant (eb b)).program.of_word (fun a => by
simpa only [WordTransducer.constant] using WordTransducer.constant_run (eb b) (ea a))
end PolyProgram
end MetricKMedian.Binary
end
end OAI
end
section
-- module Solutions.OAIQ037_KM.KMedian_Binary_BooleanListPrimitives
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
section
namespace MetricKMedian.Binary
open Turing Function Polynomial
namespace WordTransducer
abbrev prepend : Transducer where
Q := Fin 4
initial := 0
next q b := if q=0 then (1,[]) else if q=1 then (2,[b]) else if q=2 then (3,[]) else (3,[b])
finish _ := []
theorem prepend_done (xs : List Bool) : prepend.run 3 xs=xs := by
induction xs with
| nil => rfl
| cons b xs ih =>
change b::prepend.run 3 xs=b::xs
rw [ih]
theorem prepend_run (b : Bool) (xs : List Bool) :
prepend.run 0 (quote [b]++xs)=b::xs := by
change b::prepend.run 3 xs=b::xs
rw [prepend_done]
end WordTransducer
namespace PolyProgram
variable {α β : Type} {ea : α → List Bool} {eb : β → List Bool}
noncomputable def cons : PolyProgram (encodePair encodeBool id) id (fun x => x.1::x.2) :=
WordTransducer.prepend.program.of_word (fun x => by
simpa only [WordTransducer.prepend,encodePair,encodeBool,id_eq] using WordTransducer.prepend_run x.1 x.2)
end PolyProgram
end MetricKMedian.Binary
end
end OAI
end