Scheduling algorithm, machine models and routine compiler for three-machine scheduling
DefinitionOAIThreeMachineSched01This block collects the supporting declarations of the stack compiler used to prove OAI.ThreeMachine.main_theorem, part 1 of 2, in upstream module order.
Contents: the partial order and formula structures, padding, the effective description family and the dynamic program (Algorithm), the stack and tree machine models, the register-program compiler, realizers and uniform routines, and the first routine families.
Formalization Note Declarations are reproduced from upstream lean/OAI/Computability/Scheduling/ (openai/math, Apache-2.0, credit OpenAI), together with short lemmas their bodies and instances need, on Lean 4.33. Metaprograms are excluded. Where an upstream proof called the tactic poly_auto, the explicit rule applications recorded from that tactic appear instead.
import Mathlib
import Definitions.Def_ThreeMachine
set_option maxHeartbeats 2000000
set_option maxRecDepth 100000
set_option linter.all false
set_option Elab.async false
section
-- module Compat
namespace OAI
-- Lean 4.33.1 equivalents of four core theorem names introduced in Lean 4.34.
theorem ite_eq_left.{u} {c : Prop} {h : Decidable c} (hc : c) {α : Sort u} {t e : α} : (ite c t e) = t := @if_pos c h hc α t e
theorem ite_eq_right.{u} {c : Prop} {h : Decidable c} (hc : ¬c) {α : Sort u} {t e : α} : (ite c t e) = e := @if_neg c h hc α t e
theorem dite_eq_left.{u} {c : Prop} {h : Decidable c} (hc : c) {α : Sort u} {t : c → α} {e : ¬c → α} : (dite c t e) = t hc := @dif_pos c h hc α t e
theorem dite_eq_right.{u} {c : Prop} {h : Decidable c} (hc : ¬c) {α : Sort u} {t : c → α} {e : ¬c → α} : (dite c t e) = e hc := @dif_neg c h hc α t e
end OAI
end
section
-- module SeparatorWalk
namespace OAI
section
namespace ThreeMachine
namespace Structure
abbrev Layout (J : Type) [Fintype J] := J ≃ Fin (Fintype.card J)
def Layout.time {J : Type} [Fintype J] (p : Layout J) (x : J) : ℕ :=
(p x).val / 3 + 1
def Layout.Respects {J : Type} [Fintype J] (p : Layout J)
(r : J → J → Prop) : Prop :=
∀ x y, r x y → p.time x < p.time y
def Layout.Full {J : Type} [Fintype J] (p : Layout J)
(r : J → J → Prop) : Prop :=
3 ∣ Fintype.card J ∧ p.Respects r
def Layout.signature {J : Type} [Fintype J] (p : Layout J)
(priority : J → ℕ) : List ℕ :=
List.ofFn (fun i => priority (p.symm i))
def Layout.exchange {J : Type} [Fintype J] [DecidableEq J]
(p : Layout J) (x y : J) : Layout J :=
(Equiv.swap x y).trans p
@[simp] theorem exchange_time_left {J : Type} [Fintype J] [DecidableEq J]
(p : Layout J) (x y : J) : (p.exchange x y).time x = p.time y := by
simp [Layout.time, Layout.exchange]
@[simp] theorem exchange_time_right {J : Type} [Fintype J] [DecidableEq J]
(p : Layout J) (x y : J) : (p.exchange x y).time y = p.time x := by
simp [Layout.time, Layout.exchange]
end Structure
end ThreeMachine
namespace ThreeMachine.Structure
section Walk
variable {J : Type}
def PredAt (r : J → J → Prop) (time : J → ℕ) (s : ℕ) : Set J :=
{x | ∃ y, time y = s ∧ r x y}
def DescAt (r : J → J → Prop) (time : J → ℕ) (s : ℕ) : Set J :=
{x | ∃ y, time y = s ∧ r y x}
def IdealOn (W : Finset J) (r : J → J → Prop) (S : Set J) : Prop :=
∀ x ∈ W, ∀ y ∈ W, r x y → y ∈ S → x ∈ S
def PrefixOn (W : Finset J) (priority : J → ℕ) (S : Set J) : Prop :=
∀ x ∈ W, x ∈ S → ∀ y ∈ W, y ∉ S → priority x < priority y
def EarlierHigh (W : Finset J) (r : J → J → Prop) (time : J → ℕ)
(S : Set J) (s : ℕ) : Prop :=
∀ x ∈ W, time x < s → x ∉ S → x ∈ PredAt r time s
def LaterLow (W : Finset J) (r : J → J → Prop) (time : J → ℕ)
(S : Set J) (s : ℕ) : Prop :=
∀ x ∈ W, s < time x → x ∈ S → x ∈ DescAt r time s
def Separator (W : Finset J) (r : J → J → Prop) (time : J → ℕ)
(S : Set J) (s : ℕ) : Prop :=
EarlierHigh W r time S s ∧ LaterLow W r time S s
def SlotClosed (W : Finset J) (time : J → ℕ) : Prop :=
∀ x ∈ W, ∀ y, time y = time x → y ∈ W
def AdmissiblePosition (W : Finset J) (time : J → ℕ) (s : ℕ) : Prop :=
(∃ x ∈ W, time x = s) ∨ (∀ x ∈ W, s < time x)
def LocalObstruction (W : Finset J) (r : J → J → Prop)
(time priority : J → ℕ) : Prop :=
∀ x ∈ W, ∀ y ∈ W, time y < time x → priority x < priority y →
(∀ u ∈ W, r u x → time u < time y) →
∃ v ∈ W, r y v ∧ time v ≤ time x
structure Exception (W : Finset J) (r : J → J → Prop) (time : J → ℕ)
(S : Set J) (s : ℕ) (x : J) : Prop where
mem : x ∈ W
low : x ∈ S
later : s < time x
not_desc : x ∉ DescAt r time s
earliest : ∀ y ∈ W, y ∈ S → s < time y → time y < time x →
y ∈ DescAt r time s
end Walk
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section SharedWalk
variable {J : Type}
inductive AdvancePath (W : Finset J) (r : J → J → Prop) (time : J → ℕ)
(S : Set J) : ℕ → ℕ → Prop
| refl (s) : AdvancePath W r time S s s
| step {s t x} : AdvancePath W r time S s t →
Exception W r time S t x → AdvancePath W r time S s (time x)
end SharedWalk
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section IdealSeparator
variable {J : Type}
end IdealSeparator
end ThreeMachine.Structure
end
end OAI
end
section
-- module GlobalBoundaries
namespace OAI
section
namespace ThreeMachine.Structure
def GlobalUpset {J : Type} (r : J → J → Prop) (A : Set J) : Prop :=
∀ ⦃x y⦄, r x y → x ∈ A → y ∈ A
def GlobalDownset {J : Type} (r : J → J → Prop) (A : Set J) : Prop :=
∀ ⦃x y⦄, r x y → y ∈ A → x ∈ A
structure GlobalList (J : Type) where
indices : Finset ℕ
entry : ℕ → Set J
namespace GlobalList
variable {J : Type}
def Qual (K : GlobalList J) : Set J := {x | ∃ i ∈ K.indices, x ∈ K.entry i}
def Upsets (K : GlobalList J) (r : J → J → Prop) : Prop :=
∀ i ∈ K.indices, GlobalUpset r (K.entry i)
noncomputable def memberships (K : GlobalList J) (x : J) : Finset ℕ := by
classical
exact K.indices.filter (fun i => x ∈ K.entry i)
noncomputable def lastIndex (K : GlobalList J) (x : J) : ℕ :=
(K.memberships x).sup id
def KeyLT (K : GlobalList J) (rank : J → ℕ) (x y : J) : Prop :=
K.lastIndex x < K.lastIndex y ∨
K.lastIndex x = K.lastIndex y ∧ rank x < rank y
@[simp] theorem mem_memberships (K : GlobalList J) (x : J) (i : ℕ) :
i ∈ K.memberships x ↔ i ∈ K.indices ∧ x ∈ K.entry i := by
classical
simp [memberships]
theorem le_lastIndex {K : GlobalList J} {x : J} {i : ℕ}
(hi : i ∈ K.indices) (hx : x ∈ K.entry i) : i ≤ K.lastIndex x := by
exact Finset.le_sup (f := id) ((mem_memberships K x i).mpr ⟨hi, hx⟩)
noncomputable def carry (K : GlobalList J) (rank : J → ℕ) (d r : ℕ) : GlobalList J := by
classical
exact ⟨K.indices.filter (d ≤ ·), fun i =>
if i = d then K.entry i ∩ {x | r ≤ rank x} else K.entry i⟩
noncomputable def prune (K : GlobalList J) (W : Set J) : GlobalList J := by
classical
exact ⟨K.indices.filter (fun i => (K.entry i ∩ W).Nonempty), K.entry⟩
theorem prune_membership (K : GlobalList J) (W : Set J) (i : ℕ) (x : J) :
i ∈ (K.prune W).memberships x ↔
i ∈ K.indices ∧ (K.entry i ∩ W).Nonempty ∧ x ∈ K.entry i := by
classical
rw [mem_memberships]
change (i ∈ K.indices.filter (fun j => (K.entry j ∩ W).Nonempty) ∧
x ∈ K.entry i) ↔ _
rw [Finset.mem_filter]
exact and_assoc
theorem prune_qual_subset (K : GlobalList J) (W : Set J) : (K.prune W).Qual ⊆ K.Qual := by
rintro x ⟨i, hi, hx⟩
have hm := (prune_membership K W i x).mp ((mem_memberships _ _ _).mpr ⟨hi, hx⟩)
exact ⟨i, hm.1, hm.2.2⟩
theorem prune_qual (K : GlobalList J) {W : Set J} {x : J} (hx : x ∈ W) :
x ∈ (K.prune W).Qual ↔ x ∈ K.Qual := by
refine ⟨fun h => prune_qual_subset K W h, ?_⟩
rintro ⟨i, hi, hxi⟩
refine ⟨i, ?_⟩
apply (mem_memberships _ _ _).mp
exact (prune_membership K W i x).mpr ⟨hi, ⟨x, hxi, hx⟩, hxi⟩
theorem prune_lastIndex_le (K : GlobalList J) (W : Set J) (x : J) :
(K.prune W).lastIndex x ≤ K.lastIndex x := by
apply Finset.sup_le
intro i hi
have hm := (prune_membership K W i x).mp hi
exact le_lastIndex hm.1 hm.2.2
theorem prune_lastIndex (K : GlobalList J) {W : Set J} {x : J} (hx : x ∈ W) :
(K.prune W).lastIndex x = K.lastIndex x := by
apply le_antisymm (prune_lastIndex_le K W x)
apply Finset.sup_le
intro i hi
have hm := (mem_memberships K x i).mp hi
apply Finset.le_sup (f := id)
exact (prune_membership K W i x).mpr ⟨hm.1, ⟨x, hm.2, hx⟩, hm.2⟩
theorem prune_key {K : GlobalList J} {W : Set J} {rank : J → ℕ} {x y : J}
(hx : x ∈ W) (hkey : (K.prune W).KeyLT rank x y) : K.KeyLT rank x y := by
have heq := prune_lastIndex K hx
have hle := prune_lastIndex_le K W y
rcases hkey with h | ⟨h, hr⟩
· exact Or.inl (by omega)
· by_cases hlt : K.lastIndex x < K.lastIndex y
· exact Or.inl hlt
· exact Or.inr ⟨by omega, hr⟩
theorem prune_upsets {K : GlobalList J} {W : Set J} {r : J → J → Prop}
(hK : K.Upsets r) : (K.prune W).Upsets r := by
classical
intro i hi
have hi' : i ∈ K.indices ∧ (K.entry i ∩ W).Nonempty := by simpa [prune] using hi
exact hK i hi'.1
end GlobalList
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section IntervalNormalization
variable {J : Type} [Fintype J]
def Layout.FixedOutside (p q : Layout J) (W : Set J) : Prop :=
∀ x, x ∉ W → q x = p x
theorem Layout.FixedOutside.trans {p q u : Layout J} {W : Set J}
(hpq : p.FixedOutside q W) (hqu : q.FixedOutside u W) : p.FixedOutside u W :=
fun x hx => (hqu x hx).trans (hpq x hx)
theorem Layout.FixedOutside.time {p q : Layout J} {W : Set J}
(h : p.FixedOutside q W) {x : J} (hx : x ∉ W) : q.time x = p.time x := by
simp [Layout.time, h x hx]
theorem Layout.FixedOutside.position_mem {p q : Layout J} {W : Set J}
(h : p.FixedOutside q W) {x : J} (hx : x ∈ W) : p.symm (q x) ∈ W := by
by_contra hn
have he : q (p.symm (q x)) = q x := by rw [h _ hn, p.apply_symm_apply]
apply hn
rw [q.injective he]
exact hx
theorem Layout.FixedOutside.time_range {p q : Layout J} {W : Set J} {a b : ℕ}
(h : p.FixedOutside q W) (hW : ∀ x ∈ W, a < p.time x ∧ p.time x < b)
{x : J} (hx : x ∈ W) : a < q.time x ∧ q.time x < b := by
have hr := hW _ (h.position_mem hx)
simpa [Layout.time] using hr
def Layout.NormalizedOn (p : Layout J) (W : Set J)
(r : J → J → Prop) (priority : J → ℕ) : Prop :=
p.Respects r ∧ ∀ q : Layout J, q.Respects r → p.FixedOutside q W →
p.signature priority ≤ q.signature priority
end IntervalNormalization
end ThreeMachine.Structure
namespace ThreeMachine.Structure
abbrev Triple (J : Type) := {Z : Finset J // Z.card = 3}
inductive Boundary (J : Type)
| left
| actual (Z : Triple J)
| right
namespace Boundary
variable {J : Type}
def pred (r : J → J → Prop) : Boundary J → Set J
| .left => ∅
| .actual Z => {x | ∃ y ∈ Z.val, r x y}
| .right => Set.univ
def desc (r : J → J → Prop) : Boundary J → Set J
| .left => Set.univ
| .actual Z => {x | ∃ y ∈ Z.val, r y x}
| .right => ∅
def weakPred (r : J → J → Prop) : Boundary J → Set J
| .left => ∅
| .actual Z => pred r (.actual Z) ∪ (Z.val : Set J)
| .right => Set.univ
def weakDesc (r : J → J → Prop) : Boundary J → Set J
| .left => Set.univ
| .actual Z => desc r (.actual Z) ∪ (Z.val : Set J)
| .right => ∅
def reverse : Boundary J → Boundary J
| .left => .right
| .actual Z => .actual Z
| .right => .left
@[simp] theorem reverse_reverse (B : Boundary J) : B.reverse.reverse = B := by cases B <;> rfl
@[simp] theorem pred_reverse (r : J → J → Prop) (B : Boundary J) :
B.reverse.pred (fun x y => r y x) = B.desc r := by cases B <;> rfl
@[simp] theorem desc_reverse (r : J → J → Prop) (B : Boundary J) :
B.reverse.desc (fun x y => r y x) = B.pred r := by cases B <;> rfl
@[simp] theorem weakPred_reverse (r : J → J → Prop) (B : Boundary J) :
B.reverse.weakPred (fun x y => r y x) = B.weakDesc r := by cases B <;> rfl
@[simp] theorem weakDesc_reverse (r : J → J → Prop) (B : Boundary J) :
B.reverse.weakDesc (fun x y => r y x) = B.weakPred r := by cases B <;> rfl
theorem pred_downset {r : J → J → Prop}
(htrans : ∀ ⦃a b c⦄, r a b → r b c → r a c) (B : Boundary J) :
GlobalDownset r (B.pred r) := by
intro x y hxy hy
cases B with
| left => exact hy.elim
| right => trivial
| actual Z =>
obtain ⟨z, hz, hyz⟩ := hy
exact ⟨z, hz, htrans hxy hyz⟩
theorem desc_upset {r : J → J → Prop}
(htrans : ∀ ⦃a b c⦄, r a b → r b c → r a c) (B : Boundary J) :
GlobalUpset r (B.desc r) := by
intro x y hxy hx
cases B with
| left => trivial
| right => exact hx.elim
| actual Z =>
obtain ⟨z, hz, hzx⟩ := hx
exact ⟨z, hz, htrans hzx hxy⟩
theorem weakDesc_upset {r : J → J → Prop}
(htrans : ∀ ⦃a b c⦄, r a b → r b c → r a c) (B : Boundary J) :
GlobalUpset r (B.weakDesc r) := by
intro x y hxy hx
cases B with
| left => trivial
| right => exact hx.elim
| actual Z =>
rcases hx with h | h
· exact Or.inl (desc_upset htrans (.actual Z) hxy h)
· exact Or.inl ⟨x, h, hxy⟩
def At (time : J → ℕ) (T : ℕ) : Boundary J → ℕ → Prop
| .left, s => s = 0
| .actual Z, s => 1 ≤ s ∧ s ≤ T ∧ ∀ x, x ∈ Z.val ↔ time x = s
| .right, s => s = T + 1
theorem pred_time {r : J → J → Prop} {time : J → ℕ} {T s : ℕ} {B : Boundary J}
(hrespect : ∀ u v, r u v → time u < time v)
(hbound : ∀ x, 1 ≤ time x ∧ time x ≤ T) (hB : B.At time T s)
{x : J} (hx : x ∈ B.pred r) : time x < s := by
cases B with
| left => exact hx.elim
| right => have := (hbound x).2; dsimp [At] at hB; omega
| actual Z =>
obtain ⟨y, hy, hxy⟩ := hx
have he := (hB.2.2 y).mp hy
have := hrespect x y hxy
omega
theorem desc_time {r : J → J → Prop} {time : J → ℕ} {T s : ℕ} {B : Boundary J}
(hrespect : ∀ u v, r u v → time u < time v)
(hbound : ∀ x, 1 ≤ time x ∧ time x ≤ T) (hB : B.At time T s)
{x : J} (hx : x ∈ B.desc r) : s < time x := by
cases B with
| left => have := (hbound x).1; dsimp [At] at hB; omega
| right => exact hx.elim
| actual Z =>
obtain ⟨y, hy, hyx⟩ := hx
have he := (hB.2.2 y).mp hy
have := hrespect y x hyx
omega
theorem weakPred_time {r : J → J → Prop} {time : J → ℕ} {T s : ℕ} {B : Boundary J}
(hrespect : ∀ u v, r u v → time u < time v)
(hbound : ∀ x, 1 ≤ time x ∧ time x ≤ T) (hB : B.At time T s)
{x : J} (hx : x ∈ B.weakPred r) : time x ≤ s := by
cases B with
| left => exact hx.elim
| right => have := (hbound x).2; dsimp [At] at hB; omega
| actual Z =>
rcases hx with h | h
· exact (pred_time hrespect hbound hB h).le
· exact ((hB.2.2 x).mp h).le
theorem weakDesc_time {r : J → J → Prop} {time : J → ℕ} {T s : ℕ} {B : Boundary J}
(hrespect : ∀ u v, r u v → time u < time v)
(hbound : ∀ x, 1 ≤ time x ∧ time x ≤ T) (hB : B.At time T s)
{x : J} (hx : x ∈ B.weakDesc r) : s ≤ time x := by
cases B with
| left => dsimp [At] at hB; omega
| right => exact hx.elim
| actual Z =>
rcases hx with h | h
· exact (desc_time hrespect hbound hB h).le
· exact ((hB.2.2 x).mp h).ge
theorem mem_weak_at_time {r : J → J → Prop} {time : J → ℕ} {T s : ℕ} {B : Boundary J}
(hbound : ∀ x, 1 ≤ time x ∧ time x ≤ T) (hB : B.At time T s)
{x : J} (hx : time x = s) : x ∈ B.weakPred r ∧ x ∈ B.weakDesc r := by
cases B with
| left => have := (hbound x).1; dsimp [At] at hB; omega
| right => have := (hbound x).2; dsimp [At] at hB; omega
| actual Z => exact ⟨Or.inr ((hB.2.2 x).mpr hx), Or.inr ((hB.2.2 x).mpr hx)⟩
end Boundary
inductive Formula (A : Type)
| leaf (atom : A) (negative : Bool)
| conj (p q : Formula A)
| disj (p q : Formula A)
namespace Formula
variable {A J : Type}
def leaves : Formula A → ℕ
| .leaf _ _ => 1
| .conj p q | .disj p q => p.leaves + q.leaves
def eval (atoms : A → Set J) : Formula A → Set J
| .leaf a false => atoms a
| .leaf a true => (atoms a)ᶜ
| .conj p q => p.eval atoms ∩ q.eval atoms
| .disj p q => p.eval atoms ∪ q.eval atoms
def negate : Formula A → Formula A
| .leaf a b => .leaf a (!b)
| .conj p q => .disj p.negate q.negate
| .disj p q => .conj p.negate q.negate
@[simp] theorem leaves_negate (p : Formula A) : p.negate.leaves = p.leaves := by
induction p with
| leaf a b => cases b <;> rfl
| conj p q hp hq | disj p q hp hq => simp [negate, leaves, hp, hq]
@[simp] theorem eval_negate (atoms : A → Set J) (p : Formula A) :
p.negate.eval atoms = (p.eval atoms)ᶜ := by
induction p with
| leaf a b => cases b <;> simp [negate, eval]
| conj p q hp hq =>
ext x
simp only [negate, eval, hp, hq, Set.mem_union, Set.mem_compl_iff, Set.mem_inter_iff]
tauto
| disj p q hp hq => simp [negate, eval, hp, hq]
end Formula
def Described {A J : Type} (atoms : A → Set J) (W : Set J) (k : ℕ) : Prop :=
∃ p : Formula A, p.eval atoms = W ∧ p.leaves ≤ k
namespace Described
variable {A J : Type} {atoms : A → Set J} {W U : Set J} {k l : ℕ}
theorem mono (h : Described atoms W k) (hkl : k ≤ l) : Described atoms W l := by
obtain ⟨p, hp, hk⟩ := h
exact ⟨p, hp, hk.trans hkl⟩
theorem compl (h : Described atoms W k) : Described atoms Wᶜ k := by
obtain ⟨p, hp, hk⟩ := h
exact ⟨p.negate, by simp [hp], by simpa using hk⟩
theorem inter (hW : Described atoms W k) (hU : Described atoms U l) :
Described atoms (W ∩ U) (k + l) := by
obtain ⟨p, hp, hk⟩ := hW
obtain ⟨q, hq, hl⟩ := hU
exact ⟨.conj p q, by simp [Formula.eval, hp, hq], Nat.add_le_add hk hl⟩
theorem union (hW : Described atoms W k) (hU : Described atoms U l) :
Described atoms (W ∪ U) (k + l) := by
obtain ⟨p, hp, hk⟩ := hW
obtain ⟨q, hq, hl⟩ := hU
exact ⟨.disj p q, by simp [Formula.eval, hp, hq], Nat.add_le_add hk hl⟩
theorem diff (hW : Described atoms W k) (hU : Described atoms U l) :
Described atoms (W \ U) (k + l) := hW.inter hU.compl
theorem finite_union {ι : Type} (s : Finset ι) (E : ι → Set J) (b : ι → ℕ)
(hne : s.Nonempty) (hE : ∀ i ∈ s, Described atoms (E i) (b i)) :
Described atoms {x | ∃ i ∈ s, x ∈ E i} (∑ i ∈ s, b i) := by
classical
induction s using Finset.induction_on with
| empty => exact (Finset.not_nonempty_empty hne).elim
| @insert i s hi ih =>
by_cases hs : s.Nonempty
· have hrest := ih hs (fun j hj => hE j (Finset.mem_insert_of_mem hj))
have hfirst := hE i (Finset.mem_insert_self _ _)
have he : {x | ∃ j ∈ insert i s, x ∈ E j} = E i ∪ {x | ∃ j ∈ s, x ∈ E j} := by
ext x
simp only [Set.mem_ofPred_eq, Finset.mem_insert, Set.mem_union]
aesop
rw [he, Finset.sum_insert hi]
exact hfirst.union hrest
· have es : s = ∅ := Finset.not_nonempty_iff_eq_empty.mp hs
subst s
simpa using hE i (Finset.mem_insert_self i ∅)
end Described
end ThreeMachine.Structure
end
end OAI
end
section
-- module CutoffSimplification
namespace OAI
section
namespace ThreeMachine.Structure
namespace GlobalList
variable {J : Type}
noncomputable def append (K : GlobalList J) (A : Set J) : GlobalList J := by
classical
exact ⟨insert (max 1 (K.indices.sup id) + 1) K.indices,
fun i => if i = max 1 (K.indices.sup id) + 1 then A else K.entry i⟩
def nextIndex (K : GlobalList J) : ℕ := max 1 (K.indices.sup id) + 1
theorem injection_card_bound {K : GlobalList J} {r : J → J → Prop}
{W W' : Set J} {B : Finset J} {I : Finset ℕ}
(hI : I ⊆ K.indices) (hK : K.Upsets r)
(hB : (B : Set J) ⊆ W)
(hdisj : ∀ i ∈ I, ∀ j ∈ I, i ≠ j →
∀ x ∈ W, x ∈ K.entry i → x ∉ K.entry j)
(hmeet : ∀ i ∈ I, (K.entry i ∩ W').Nonempty)
(hpred : ∀ x ∈ W', x ∈ K.Qual → ∃ z ∈ B, r x z) : I.card ≤ B.card := by
classical
have hex : ∀ i ∈ I, ∃ z ∈ B, z ∈ K.entry i := by
intro i hi
obtain ⟨x, hxi, hxW⟩ := hmeet i hi
obtain ⟨z, hz, hxz⟩ := hpred x hxW ⟨i, hI hi, hxi⟩
exact ⟨z, hz, hK i (hI hi) hxz hxi⟩
let f : ↥I → ↥B := fun i =>
⟨Classical.choose (hex i.val i.property), (Classical.choose_spec (hex i.val i.property)).1⟩
have hf : ∀ i : ↥I, (f i).val ∈ K.entry i.val := fun i =>
(Classical.choose_spec (hex i.val i.property)).2
have hinj : Function.Injective f := by
intro i j he
apply Subtype.ext
by_contra hne
have e : (f i).val = (f j).val := congrArg Subtype.val he
exact hdisj i.val i.property j.val j.property hne (f i).val
(hB (f i).property) (hf i) (e ▸ hf j)
simpa using Fintype.card_le_of_injective f hinj
end GlobalList
end ThreeMachine.Structure
namespace ThreeMachine.Structure
variable {J : Type}
def Window (time : J → ℕ) (a b : ℕ) : Set J := {x | a < time x ∧ time x < b}
namespace Boundary
theorem desc_subset_weakDesc (r : J → J → Prop) (B : Boundary J) :
B.desc r ⊆ B.weakDesc r := by
cases B with
| left => exact Set.Subset.rfl
| right => exact Set.Subset.rfl
| actual Z => exact Set.subset_union_left
def Separates (B : Boundary J) (r : J → J → Prop) (time : J → ℕ)
(W S : Set J) (s : ℕ) : Prop :=
(∀ x ∈ W, time x < s → x ∉ S → x ∈ B.pred r) ∧
(∀ x ∈ W, s < time x → x ∈ S → x ∈ B.desc r)
def before (B : Boundary J) (r : J → J → Prop) (H : Set J) : Set J :=
B.pred r ∪ (H \ B.weakDesc r)
theorem separates_description {r : J → J → Prop} {time : J → ℕ} {T s : ℕ}
{B : Boundary J} {W S H : Set J}
(hrespect : ∀ u v, r u v → time u < time v)
(hbound : ∀ x, 1 ≤ time x ∧ time x ≤ T) (hB : B.At time T s)
(hsep : B.Separates r time W S s) (hagree : ∀ x ∈ W, x ∈ H ↔ x ∈ S) :
∀ x ∈ W, x ∈ B.before r H ↔ time x < s := by
intro x hx
constructor
· rintro (hP | ⟨hH, hnD⟩)
· exact pred_time hrespect hbound hB hP
· have hS := (hagree x hx).mp hH
by_contra hn
have hle : s ≤ time x := by omega
rcases hle.eq_or_lt with he | hl
· exact hnD (mem_weak_at_time hbound hB he.symm).2
· exact hnD (desc_subset_weakDesc r B (hsep.2 x hx hl hS))
· intro hlt
by_cases hS : x ∈ S
· refine Or.inr ⟨(hagree x hx).mpr hS, ?_⟩
intro hD
have := weakDesc_time hrespect hbound hB hD
omega
· exact Or.inl (hsep.1 x hx hlt hS)
end Boundary
def PastInvariant (r : J → J → Prop) (time : J → ℕ)
(K : GlobalList J) (A : Boundary J) (a : ℕ) : Prop :=
∀ x ∈ K.Qual, time x ≤ a → x ∈ A.weakPred r
theorem past_prune {r : J → J → Prop} {time : J → ℕ}
{K : GlobalList J} {A : Boundary J} {a : ℕ} {W : Set J}
(h : PastInvariant r time K A a) : PastInvariant r time (K.prune W) A a := by
intro x hx ht
exact h x (K.prune_qual_subset W hx) ht
theorem global_high_identity {r : J → J → Prop} {time : J → ℕ} {T a b : ℕ}
{A B : Boundary J} {K : GlobalList J} {S : Set J}
(hrespect : ∀ u v, r u v → time u < time v)
(hbound : ∀ x, 1 ≤ time x ∧ time x ≤ T)
(hA : A.At time T a) (hB : B.At time T b)
(hlabels : ∀ x ∈ Window time a b, x ∈ K.Qual ↔ x ∉ S)
(hhigh : ∀ x ∈ Window time a b, x ∉ S → x ∈ B.pred r)
(hpast : PastInvariant r time K A a) :
Window time a b \ S = K.Qual ∩ B.pred r ∩ (A.weakPred r)ᶜ := by
ext x
constructor
· rintro ⟨hx, hS⟩
refine ⟨⟨(hlabels x hx).mpr hS, hhigh x hx hS⟩, ?_⟩
intro hbad
have ht := A.weakPred_time hrespect hbound hA hbad
exact (not_le_of_gt hx.1) ht
· rintro ⟨⟨hq, hP⟩, hnP⟩
have hxb := B.pred_time hrespect hbound hB hP
have hax : a < time x := by
by_contra h
exact hnP (hpast x hq (by omega))
exact ⟨⟨hax, hxb⟩, (hlabels x ⟨hax, hxb⟩).mp hq⟩
theorem global_low_identity {r : J → J → Prop} {time : J → ℕ}
{T a b ap bp v : ℕ} {A' B B' V : Boundary J} {S Sstar H : Set J}
(hrespect : ∀ u z, r u z → time u < time z)
(hbound : ∀ x, 1 ≤ time x ∧ time x ≤ T)
(hA' : A'.At time T ap) (hB : B.At time T b)
(hB' : B'.At time T bp) (hV : V.At time T v)
(ha : a ≤ ap) (_hap : ap < bp) (hbp : bp ≤ v) (hvb : v < b)
(hagree : ∀ x ∈ Window time a b, x ∈ H ↔ x ∈ S)
(hsub : ∀ x ∈ Window time a b, x ∈ S → x ∈ Sstar)
(hcenter : V.Separates r time (Window time a b) Sstar v)
(hend : B'.Separates r time (Window time a v) S bp)
(hlow : ∀ x ∈ Window time ap bp, x ∈ S → x ∈ A'.desc r ∩ B.pred r) :
Window time ap bp ∩ S =
A'.desc r ∩ B.pred r ∩ (B'.weakDesc r)ᶜ ∩ (V.weakDesc r)ᶜ ∩ H := by
ext x
constructor
· rintro ⟨hx, hS⟩
have hxW : x ∈ Window time a b := ⟨by have := hx.1; omega, by have := hx.2; omega⟩
refine ⟨⟨⟨hlow x hx hS, ?_⟩, ?_⟩, (hagree x hxW).mpr hS⟩
· intro hbad
have := B'.weakDesc_time hrespect hbound hB' hbad
have := hx.2
omega
· intro hbad
have := V.weakDesc_time hrespect hbound hV hbad
have := hx.2
omega
· rintro ⟨⟨⟨⟨hD, hP⟩, hnB⟩, hnV⟩, hH⟩
have hapx := A'.desc_time hrespect hbound hA' hD
have hxb := B.pred_time hrespect hbound hB hP
have hxW : x ∈ Window time a b := ⟨by omega, hxb⟩
have hS := (hagree x hxW).mp hH
have hxv : time x < v := by
by_contra h
have hle : v ≤ time x := by omega
rcases hle.eq_or_lt with he | hl
· exact hnV (Boundary.mem_weak_at_time hbound hV he.symm).2
· exact hnV (V.desc_subset_weakDesc r (hcenter.2 x hxW hl (hsub x hxW hS)))
have hxbp : time x < bp := by
by_contra h
have hle : bp ≤ time x := by omega
rcases hle.eq_or_lt with he | hl
· exact hnB (Boundary.mem_weak_at_time hbound hB' he.symm).2
· have hxE : x ∈ Window time a v := ⟨by omega, hxv⟩
exact hnB (B'.desc_subset_weakDesc r (hend.2 x hxE hl hS))
exact ⟨⟨hapx, hxbp⟩, hS⟩
end ThreeMachine.Structure
namespace ThreeMachine.Structure
variable {J : Type}
end ThreeMachine.Structure
end
end OAI
end
section
-- module FrameInvariants
namespace OAI
section
namespace ThreeMachine.Structure
namespace Layout
variable {J : Type} [Fintype J]
theorem time_bounds (p : Layout J) (hfull : 3 ∣ Fintype.card J) (x : J) :
1 ≤ p.time x ∧ p.time x ≤ Fintype.card J / 3 := by
obtain ⟨T, hT⟩ := hfull
have hp := (p x).isLt
dsimp [time]
omega
noncomputable def slot (p : Layout J) (s : ℕ) : Finset J := by
classical
exact Finset.univ.filter (fun x => p.time x = s)
@[simp] theorem mem_slot (p : Layout J) (s : ℕ) (x : J) :
x ∈ p.slot s ↔ p.time x = s := by
classical
simp [slot]
theorem card_slot (p : Layout J) (hfull : 3 ∣ Fintype.card J) (s : ℕ)
(hs : 1 ≤ s) (hsT : s ≤ Fintype.card J / 3) : (p.slot s).card = 3 := by
classical
obtain ⟨T, hT⟩ := hfull
let i : Fin (Fintype.card J) := ⟨3 * (s - 1), by omega⟩
let j : Fin (Fintype.card J) := ⟨3 * (s - 1) + 1, by omega⟩
let k : Fin (Fintype.card J) := ⟨3 * (s - 1) + 2, by omega⟩
apply Finset.card_eq_three.mpr
refine ⟨p.symm i, p.symm j, p.symm k, ?_, ?_, ?_, ?_⟩
· intro he
have hev := congrArg Fin.val (p.symm.injective he)
dsimp [i, j] at hev
omega
· intro he
have hev := congrArg Fin.val (p.symm.injective he)
dsimp [i, k] at hev
omega
· intro he
have hev := congrArg Fin.val (p.symm.injective he)
dsimp [j, k] at hev
omega
· ext x
simp only [mem_slot, Finset.mem_insert, Finset.mem_singleton]
have hxi : x = p.symm i ↔ (p x).val = 3 * (s - 1) := by
rw [Equiv.eq_symm_apply]
exact Fin.ext_iff
have hxj : x = p.symm j ↔ (p x).val = 3 * (s - 1) + 1 := by
rw [Equiv.eq_symm_apply]
exact Fin.ext_iff
have hxk : x = p.symm k ↔ (p x).val = 3 * (s - 1) + 2 := by
rw [Equiv.eq_symm_apply]
exact Fin.ext_iff
rw [hxi, hxj, hxk]
dsimp [time]
omega
noncomputable def triple (p : Layout J) (hfull : 3 ∣ Fintype.card J)
(s : ℕ) (hs : 1 ≤ s) (hsT : s ≤ Fintype.card J / 3) : Triple J :=
⟨p.slot s, p.card_slot hfull s hs hsT⟩
def reverse (p : Layout J) : Layout J := p.trans Fin.revPerm
@[simp] theorem reverse_reverse (p : Layout J) : p.reverse.reverse = p := by
ext x
simp [reverse]
theorem reverse_time (p : Layout J) (hfull : 3 ∣ Fintype.card J) (x : J) :
p.reverse.time x = Fintype.card J / 3 + 1 - p.time x := by
obtain ⟨T, hT⟩ := hfull
have hp := (p x).isLt
change (Fintype.card J - ((p x).val + 1)) / 3 + 1 =
Fintype.card J / 3 + 1 - ((p x).val / 3 + 1)
omega
end Layout
namespace Boundary
variable {J : Type} [Fintype J]
end Boundary
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section IntervalHelpers
variable {J : Type} [Fintype J]
theorem Layout.FixedOutside.window {p q : Layout J} {W : Set J} {a b : ℕ}
(h : p.FixedOutside q W) (hW : ∀ x, x ∈ W ↔ x ∈ Window p.time a b) :
∀ x, x ∈ W ↔ x ∈ Window q.time a b := by
intro x
constructor
· exact h.time_range (fun z hz => (hW z).mp hz)
· intro hx
by_contra hn
have he := h.time hn
apply hn
apply (hW x).mpr
change a < q.time x ∧ q.time x < b at hx
change a < p.time x ∧ p.time x < b
simpa only [he] using hx
theorem Layout.FixedOutside.boundary {p q : Layout J} {W : Set J} {a b s T : ℕ}
{B : Boundary J} (h : p.FixedOutside q W)
(hW : ∀ x, x ∈ W ↔ x ∈ Window p.time a b)
(hs : s ≤ a ∨ b ≤ s) (hB : B.At p.time T s) : B.At q.time T s := by
cases B with
| left => exact hB
| right => exact hB
| actual Z =>
refine ⟨hB.1, hB.2.1, ?_⟩
intro x
by_cases hx : x ∈ W
· have hp := (hW x).mp hx
have hq := (h.window hW x).mp hx
have hnp : p.time x ≠ s := by rcases hs with hs | hs <;> dsimp [Window] at hp <;> omega
have hnq : q.time x ≠ s := by rcases hs with hs | hs <;> dsimp [Window] at hq <;> omega
rw [hB.2.2]
exact iff_of_false hnp hnq
· rw [hB.2.2, h.time hx]
theorem PastInvariant.reorder {r : J → J → Prop} {p q : Layout J}
{K : GlobalList J} {A : Boundary J} {a b : ℕ} {W : Set J}
(hpast : PastInvariant r p.time K A a) (hfix : p.FixedOutside q W)
(hW : ∀ x, x ∈ W ↔ x ∈ Window p.time a b) :
PastInvariant r q.time K A a := by
intro x hx htime
have hnW : x ∉ W := by
intro hw
have h := ((hfix.window hW) x).mp hw
exact (not_lt_of_ge htime) h.1
have ht : p.time x = q.time x := (hfix.time hnW).symm
exact hpast x hx (ht ▸ htime)
def SwapInvariant [DecidableEq J] (r : J → J → Prop) (p : Layout J)
(W : Set J) (K : GlobalList J) (rank : J → ℕ) (A : Boundary J) (a : ℕ) : Prop :=
∀ q : Layout J, p.FixedOutside q W → q.Respects r →
∀ x ∈ W, x ∉ A.desc r → ∀ y, q.time y = a → y ∈ K.Qual →
K.KeyLT rank x y → ¬(q.exchange x y).Respects r
theorem SwapInvariant.reorder [DecidableEq J] {r : J → J → Prop} {p q : Layout J}
{W : Set J} {K : GlobalList J} {rank : J → ℕ} {A : Boundary J} {a : ℕ}
(h : SwapInvariant r p W K rank A a) (hfix : p.FixedOutside q W) :
SwapInvariant r q W K rank A a := by
intro u hqu hu x hx hnx y hy hyq hkey
exact h u (hfix.trans hqu) hu x hx hnx y hy hyq hkey
end IntervalHelpers
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section BoundaryWalk
variable {J : Type} [Fintype J]
end BoundaryWalk
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section VaryingWalk
variable {J : Type}
inductive CutoffWalk (E : Finset J) (r : J → J → Prop) (time priority : J → ℕ)
(Sfinal : Set J) (a : ℕ) : ℕ → Prop
| refl : CutoffWalk E r time priority Sfinal a a
| step {s : ℕ} {x : J} {U : Set J}
(prev : CutoffWalk E r time priority Sfinal a s)
(ideal : IdealOn E r U) (isPrefix : PrefixOn E priority U)
(below : ∀ z ∈ E, z ∈ U → z ∈ Sfinal)
(exception : Exception E r time U s x) :
CutoffWalk E r time priority Sfinal a (time x)
end VaryingWalk
section PastUpdate
variable {J : Type} [Fintype J]
end PastUpdate
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section ChildSwaps
variable {J : Type} [Fintype J] [DecidableEq J]
theorem swap_prune {r : J → J → Prop} {p : Layout J}
{W : Set J} {K : GlobalList J} {rank : J → ℕ} {A : Boundary J} {a : ℕ}
(hparent : SwapInvariant r p W K rank A a) :
SwapInvariant r p W (K.prune W) rank A a := by
intro q hfix hq x hx hnx y hy hyq hkey
exact hparent q hfix hq x hx hnx y hy (K.prune_qual_subset W hyq)
(GlobalList.prune_key hx hkey)
end ChildSwaps
end ThreeMachine.Structure
end
end OAI
end
section
-- module RunCertificates
namespace OAI
section
namespace ThreeMachine.Structure
section RunCertificates
variable {J A : Type}
def RankTail (rank : J → ℕ) (k : ℕ) : Set J := {x | k ≤ rank x}
structure RunData (K : GlobalList J) (rank : J → ℕ) (atoms : A → Set J)
(W : Set J) where
base : ℕ → Set J
threshold : ℕ → ℕ
second : Set J
entry_eq : ∀ i ∈ K.indices, K.entry i = base i ∩ RankTail rank (threshold i)
simple : ∀ i ∈ K.indices, i ≠ 0 → Described atoms (base i) 2
first_small : Described atoms (base 0) 24
second_small : Described atoms second 1
second_eq : base 1 = second
cover : ∀ x ∈ W, x ∉ second → x ∈ base 0
pair : 0 ∈ K.indices → ∀ x ∈ W, x ∈ second → 1 ∈ K.indices ∧ x ∈ K.entry 1
namespace RunData
variable {K : GlobalList J} {rank : J → ℕ} {atoms : A → Set J} {W W' : Set J}
noncomputable def carry (D : RunData K rank atoms W) (d k : ℕ) :
RunData (K.carry rank d k) rank atoms W := by
classical
refine { base := D.base
threshold := fun i => if i = d then max (D.threshold i) k else D.threshold i
second := D.second
entry_eq := ?_
simple := ?_
first_small := D.first_small
second_small := D.second_small
second_eq := D.second_eq
cover := D.cover
pair := ?_ }
· intro i hi
have hi' : i ∈ K.indices ∧ d ≤ i := Finset.mem_filter.mp hi
change (if i = d then K.entry i ∩ {x | k ≤ rank x} else K.entry i) = _
rw [D.entry_eq i hi'.1]
by_cases hid : i = d
· simp only [hid, ite_eq_left]
ext x
simp only [Set.mem_inter_iff, RankTail, Set.mem_ofPred_eq, max_le_iff]
tauto
· simp only [hid, ite_false]
· intro i hi hn
exact D.simple i (Finset.mem_filter.mp hi).1 hn
· intro hzero x hx hxD
have hd : d = 0 := by have := (Finset.mem_filter.mp hzero).2; omega
have hz : 0 ∈ K.indices := (Finset.mem_filter.mp hzero).1
obtain ⟨h1, hx1⟩ := D.pair hz x hx hxD
refine ⟨Finset.mem_filter.mpr ⟨h1, by omega⟩, ?_⟩
change x ∈ if 1 = d then _ else _
simpa [hd] using hx1
noncomputable def prune (D : RunData K rank atoms W) (hsub : W' ⊆ W) :
RunData (K.prune W') rank atoms W' := by
classical
refine { base := D.base, threshold := D.threshold, second := D.second
entry_eq := ?_, simple := ?_, first_small := D.first_small
second_small := D.second_small, second_eq := D.second_eq
cover := fun x hx hn => D.cover x (hsub hx) hn
pair := ?_ }
· intro i hi
exact D.entry_eq i (Finset.mem_filter.mp hi).1
· intro i hi hn
exact D.simple i (Finset.mem_filter.mp hi).1 hn
· intro hzero x hx hxD
obtain ⟨h1, hx1⟩ := D.pair (Finset.mem_filter.mp hzero).1 x (hsub hx) hxD
exact ⟨Finset.mem_filter.mpr ⟨h1, ⟨x, hx1, hx⟩⟩, hx1⟩
noncomputable def append (D : RunData K rank atoms W) (I : Set J)
(hI : Described atoms I 2) : RunData (K.append I) rank atoms W := by
classical
have hnext : 2 ≤ K.nextIndex := by dsimp [GlobalList.nextIndex]; omega
refine { base := fun i => if i = K.nextIndex then I else D.base i
threshold := fun i => if i = K.nextIndex then 0 else D.threshold i
second := D.second
entry_eq := ?_, simple := ?_, first_small := ?_
second_small := D.second_small, second_eq := ?_
cover := ?_, pair := ?_ }
· intro i hi
change i ∈ insert K.nextIndex K.indices at hi
change (if i = K.nextIndex then I else K.entry i) = _
by_cases he : i = K.nextIndex
· simp only [he, ite_eq_left]
ext x
simp [RankTail]
· have hiK : i ∈ K.indices := (Finset.mem_insert.mp hi).resolve_left he
simpa only [he, ite_false] using D.entry_eq i hiK
· intro i hi hn
change i ∈ insert K.nextIndex K.indices at hi
by_cases he : i = K.nextIndex
· simpa only [he, ite_eq_left] using hI
· simpa only [he, ite_false] using D.simple i ((Finset.mem_insert.mp hi).resolve_left he) hn
· simpa only [show 0 ≠ K.nextIndex by omega, ite_false] using D.first_small
· simpa only [show 1 ≠ K.nextIndex by omega, ite_false] using D.second_eq
· intro x hx hn
simpa only [show 0 ≠ K.nextIndex by omega, ite_false] using D.cover x hx hn
· intro hz x hx hxD
change 0 ∈ insert K.nextIndex K.indices at hz
have hzK : 0 ∈ K.indices := (Finset.mem_insert.mp hz).resolve_left (by omega)
obtain ⟨h1, hx1⟩ := D.pair hzK x hx hxD
refine ⟨Finset.mem_insert_of_mem h1, ?_⟩
change x ∈ if 1 = K.nextIndex then I else K.entry 1
simpa only [show 1 ≠ K.nextIndex by omega, ite_false] using hx1
theorem entry_small (D : RunData K rank atoms W)
(hrank : ∀ k, Described atoms (RankTail rank k) 1) {i : ℕ} (hi : i ∈ K.indices) :
Described atoms (K.entry i) 25 := by
rw [D.entry_eq i hi]
by_cases he : i = 0
· subst i
exact D.first_small.inter (hrank _)
· exact ((D.simple i hi he).inter (hrank _)).mono (by omega)
noncomputable def flatEntry (D : RunData K rank atoms W) (i : ℕ) : Set J :=
if i = 0 then D.second ∪ RankTail rank (D.threshold 0) else K.entry i
end RunData
end RunCertificates
end ThreeMachine.Structure
namespace ThreeMachine.Structure
namespace GlobalList
variable {J : Type}
def empty : GlobalList J := ⟨∅, fun _ => ∅⟩
def one (A : Set J) : GlobalList J := ⟨{1}, fun _ => A⟩
def pair (A B : Set J) : GlobalList J := ⟨{0, 1}, fun i => if i = 0 then A else B⟩
@[simp] theorem qual_empty : (empty : GlobalList J).Qual = ∅ := by
ext x
simp [Qual, empty]
@[simp] theorem qual_one (A : Set J) : (one A).Qual = A := by
ext x
simp [Qual, one]
@[simp] theorem qual_pair (A B : Set J) : (pair A B).Qual = A ∪ B := by
ext x
simp [Qual, pair]
def InjectionDisjoint (K : GlobalList J) (W : Set J) : Prop :=
∀ i ∈ K.indices, 2 ≤ i → ∀ j ∈ K.indices, 2 ≤ j → i ≠ j →
∀ x ∈ W, x ∈ K.entry i → x ∉ K.entry j
theorem InjectionDisjoint.prune {K : GlobalList J} {W W' : Set J}
(h : K.InjectionDisjoint W) (hsub : W' ⊆ W) : (K.prune W').InjectionDisjoint W' := by
classical
intro i hi h2i j hj h2j hn x hx hxi hxj
exact h i (Finset.mem_filter.mp hi).1 h2i j (Finset.mem_filter.mp hj).1 h2j hn
x (hsub hx) hxi hxj
theorem pruned_length {K : GlobalList J} {r : J → J → Prop}
{W W' : Set J} {B : Triple J}
(hup : K.Upsets r) (hdisj : K.InjectionDisjoint W)
(hB : ∀ z ∈ B.val, z ∈ W)
(hhigh : ∀ x ∈ W', x ∈ K.Qual → ∃ z ∈ B.val, r x z) :
(K.prune W').indices.card ≤ 5 := by
classical
let P := K.prune W'
let I := P.indices.filter (2 ≤ ·)
have hI : ∀ i ∈ I, i ∈ K.indices := by
intro i hi
exact (Finset.mem_filter.mp (Finset.mem_filter.mp hi).1).1
have hactive : ∀ i ∈ I, ∃ x ∈ W', x ∈ K.entry i := by
intro i hi
obtain ⟨x, hxK, hxW⟩ := (Finset.mem_filter.mp (Finset.mem_filter.mp hi).1).2
exact ⟨x, hxW, hxK⟩
have hcap : I.card ≤ B.val.card := injection_card_bound (fun _ hi => hI _ hi) hup
(fun _ hz => hB _ hz)
(fun i hi j hj hn x hx hxi hxj => hdisj i (hI i hi) (Finset.mem_filter.mp hi).2
j (hI j hj) (Finset.mem_filter.mp hj).2 hn x hx hxi hxj)
(fun i hi => by obtain ⟨x, hxW, hxi⟩ := hactive i hi; exact ⟨x, hxi, hxW⟩)
(fun x hx hxq => hhigh x hx hxq)
have hsmall : (P.indices.filter (fun i => i < 2)).card ≤ 2 := by
apply le_trans (Finset.card_le_card (t := {0, 1}) ?_) (by decide)
intro i hi
have hi2 := (Finset.mem_filter.mp hi).2
simp only [Finset.mem_insert, Finset.mem_singleton]
omega
have hsum := Finset.card_filter_add_card_filter_not (s := P.indices) (p := fun i => 2 ≤ i)
have hnot : P.indices.filter (fun i => ¬2 ≤ i) = P.indices.filter (fun i => i < 2) := by
simp only [not_le]
rw [hnot] at hsum
change I.card + _ = P.indices.card at hsum
have hthree := B.property
change (K.prune W').indices.card ≤ 5
dsimp only [P] at hsum hsmall
omega
end GlobalList
namespace RunData
variable {J A : Type} {rank : J → ℕ} {atoms : A → Set J} {W : Set J}
noncomputable def root (htrue : Described atoms Set.univ 1) :
RunData (GlobalList.one Set.univ) rank atoms W := by
refine { base := fun _ => Set.univ, threshold := fun _ => 0, second := Set.univ
entry_eq := ?_, simple := ?_, first_small := htrue.mono (by omega)
second_small := htrue, second_eq := rfl, cover := ?_, pair := ?_ }
· intro i _
ext x
simp [GlobalList.one, RankTail]
· intro i _ _
exact htrue.mono (by omega)
· intro x _ _
trivial
· intro hz
simp [GlobalList.one] at hz
noncomputable def switched {G D : Set J} (hG : Described atoms G 24)
(hD : Described atoms D 1) (hcover : ∀ x ∈ W, x ∉ D → x ∈ G) (k : ℕ) :
RunData (GlobalList.pair (G ∩ RankTail rank k) D) rank atoms W := by
refine { base := fun i => if i = 0 then G else D
threshold := fun i => if i = 0 then k else 0
second := D
entry_eq := ?_, simple := ?_, first_small := ?_
second_small := hD, second_eq := ?_, cover := ?_, pair := ?_ }
· intro i _
by_cases he : i = 0
· simp [GlobalList.pair, he]
· ext x
simp [GlobalList.pair, he, RankTail]
· intro i _ hn
simpa only [hn, ite_false] using hD.mono (show 1 ≤ 2 by omega)
· simpa using hG
· simp
· simpa using hcover
· intro _ x _ hx
exact ⟨by simp [GlobalList.pair], by simpa [GlobalList.pair] using hx⟩
end RunData
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section NumericWalk
variable {J : Type}
def PriorityCut (priority : J → ℕ) (k : ℕ) : Set J := {x | priority x < k}
structure NumericWalkData (E : Finset J) (r : J → J → Prop)
(time priority : J → ℕ) (a lo count : ℕ) where
position : Fin (count+1) → ℕ
first : position 0 = a
endpoint : ∀ i, position i = a ∨ ∃ x ∈ E, time x = position i
separator : ∀ i, Separator E r time (PriorityCut priority (lo+i.val)) (position i)
history : ∀ i, CutoffWalk E r time priority (PriorityCut priority (lo+i.val)) a (position i)
steps : ∀ i : Fin count,
AdvancePath E r time (PriorityCut priority (lo+i.val+1))
(position i.castSucc) (position i.succ) ∧
Separator E r time (PriorityCut priority (lo+i.val)) (position i.succ)
end NumericWalk
end ThreeMachine.Structure
end
end OAI
end
section
-- module PriorityUpdates
namespace OAI
section
namespace ThreeMachine.Structure
section PriorityEncoding
variable {J : Type}
namespace GlobalList
noncomputable def keyValue (K : GlobalList J) (rank : J → ℕ) (B : ℕ) (x : J) : ℕ :=
K.lastIndex x * B + rank x
noncomputable def samePriority (K : GlobalList J) (rank : J → ℕ) (B : ℕ)
(P : Set J) (x : J) : ℕ := by
classical
exact if x ∈ K.Qual then B + K.keyValue rank B x
else if x ∈ P then rank x else B + (K.indices.sup id + 1) * B + rank x
end GlobalList
end PriorityEncoding
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section SwitchedPriorities
variable {J : Type}
noncomputable def switchPriority (rank : J → ℕ) (B : ℕ) (D : Set J) (x : J) : ℕ := by
classical
exact if x ∈ D then B + rank x else rank x
namespace GlobalList
end GlobalList
end SwitchedPriorities
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section ReverseSeeds
variable {J A : Type}
structure ReverseSeed (r : J → J → Prop) (time : J → ℕ) (atoms : A → Set J)
(W : Set J) (B : Boundary J) (b : ℕ) where
predicate : Set J
downset : GlobalUpset (fun x y => r y x) predicate
small : Described atoms predicate 24
cover : ∀ x ∈ W, x ∉ B.pred r → x ∈ predicate
earlier : ∀ x ∈ predicate, time x < b
variable {r : J → J → Prop} {time : J → ℕ} {atoms : A → Set J}
theorem reverse_seed_at_edge {T a b ap bp v : ℕ} {B B' V : Boundary J}
{W E W' S Sstar Hext : Set J}
(htrans : ∀ ⦃x y z⦄, r x y → r y z → r x z)
(hrespect : ∀ x y, r x y → time x < time y)
(hbound : ∀ x, 1 ≤ time x ∧ time x ≤ T)
(hB : B.At time T b) (hB' : B'.At time T bp) (hV : V.At time T v)
(hW : W = Window time a b) (hE : E = Window time a v)
(hW' : W' = Window time ap bp)
(hapos : a ≤ ap) (hab : ap < bp) (hbv : bp ≤ v) (hvb : v < b)
(hhigh : ∀ x ∈ W', x ∉ S → x ∈ B'.pred r)
(hcovers : ∀ x ∈ W, x ∈ S → x ∈ B.pred r)
(hbelow : ∀ x ∈ W, x ∈ S → x ∈ Sstar)
(hcenter : V.Separates r time W Sstar v)
(hsep : B'.Separates r time E S bp)
(hH : GlobalUpset (fun x y => r y x) Hext)
(hagrees : ∀ x ∈ W, x ∈ Hext ↔ x ∈ S)
(hsmall : Described atoms Hext 21)
(hPsmall : Described atoms (B.pred r) 1)
(hDbsmall : Described atoms (B'.weakDesc r) 1)
(hDvsmall : Described atoms (V.weakDesc r) 1) :
Nonempty (ReverseSeed r time atoms W' B' bp) := by
let G := ((B.pred r \ B'.weakDesc r) \ V.weakDesc r) ∩ Hext
have hup : GlobalUpset (fun x y => r y x) G := by
intro x y hyx hx
refine ⟨⟨⟨Boundary.pred_downset htrans B hyx hx.1.1.1, ?_⟩, ?_⟩, hH hyx hx.2⟩
· intro hy
exact hx.1.1.2 (Boundary.weakDesc_upset htrans B' hyx hy)
· intro hy
exact hx.1.2 (Boundary.weakDesc_upset htrans V hyx hy)
have hGsmall : Described atoms G 24 := by
exact ((hPsmall.diff hDbsmall).diff hDvsmall).inter hsmall
refine ⟨⟨G, hup, hGsmall, ?_, ?_⟩⟩
· intro x hx hnP
have hxt : x ∈ Window time ap bp := hW' ▸ hx
change ap < time x ∧ time x < bp at hxt
have hxW : x ∈ W := hW ▸ show x ∈ Window time a b from ⟨by omega, by omega⟩
have hxS : x ∈ S := by by_contra hn; exact hnP (hhigh x hx hn)
refine ⟨⟨⟨hcovers x hxW hxS, ?_⟩, ?_⟩, (hagrees x hxW).mpr hxS⟩
· intro hD
have := Boundary.weakDesc_time hrespect hbound hB' hD
omega
· intro hD
have := Boundary.weakDesc_time hrespect hbound hV hD
omega
· intro x hx
have hxb := Boundary.pred_time hrespect hbound hB hx.1.1.1
by_contra hn
have hxW : x ∈ W := hW ▸ show x ∈ Window time a b from ⟨by omega, hxb⟩
have hxS := (hagrees x hxW).mp hx.2
have hxv : time x < v := by
by_contra hnv
rcases (show v ≤ time x by omega).eq_or_lt with he | hl
· exact hx.1.2 (Boundary.mem_weak_at_time hbound hV he.symm).2
· exact hx.1.2 (V.desc_subset_weakDesc r (hcenter.2 x hxW hl (hbelow x hxW hxS)))
have hxE : x ∈ E := hE ▸ show x ∈ Window time a v from ⟨by omega, hxv⟩
rcases (show bp ≤ time x by omega).eq_or_lt with he | hl
· exact hx.1.1.2 (Boundary.mem_weak_at_time hbound hB' he.symm).2
· exact hx.1.1.2 (B'.desc_subset_weakDesc r (hsep.2 x hxE hl hxS))
variable [Fintype J]
def ReverseSeed.reorder {p q : Layout J} {W : Set J} {B : Boundary J} {a b : ℕ}
(D : ReverseSeed r p.time atoms W B b)
(hW : W = Window p.time a b) (hfix : p.FixedOutside q W) :
ReverseSeed r q.time atoms W B b := by
refine { D with earlier := ?_ }
intro x hx
by_cases hxW : x ∈ W
· exact ((hfix.time_range (fun z hz => hW ▸ hz) hxW)).2
· rw [hfix.time hxW]
exact D.earlier x hx
end ReverseSeeds
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section DescriptionInterface
variable {J A : Type} {r : J → J → Prop} {rank : J → ℕ} {atoms : A → Set J}
structure AtomSupport (atoms : A → Set J) (r : J → J → Prop) (rank : J → ℕ) : Prop where
truth : Described atoms Set.univ 1
falsity : Described atoms ∅ 1
rankTail : ∀ k, Described atoms (RankTail rank k) 1
pred : ∀ B : Boundary J, Described atoms (B.pred r) 1
desc : ∀ B : Boundary J, Described atoms (B.desc r) 1
weakPred : ∀ B : Boundary J, Described atoms (B.weakPred r) 1
weakDesc : ∀ B : Boundary J, Described atoms (B.weakDesc r) 1
triple : ∀ Z : Triple J, Described atoms (Z.val : Set J) 1
namespace RunData
variable {K : GlobalList J} {W : Set J}
theorem qual_small (D : RunData K rank atoms W) (hA : AtomSupport atoms r rank)
(hcard : K.indices.card ≤ 5) : Described atoms K.Qual 195 := by
classical
by_cases hne : K.indices.Nonempty
· have hd := Described.finite_union K.indices K.entry (fun _ => 25) hne
(fun i hi => D.entry_small hA.rankTail hi)
apply hd.mono
simp only [Finset.sum_const, smul_eq_mul]
omega
· have hzero : K.indices = ∅ := Finset.not_nonempty_iff_eq_empty.mp hne
have he : K.Qual = ∅ := by ext x; simp [GlobalList.Qual, hzero]
rw [he]
exact hA.falsity.mono (by omega)
end RunData
theorem global_child_small
{A' B B' V : Boundary J} {W' S Stilde : Set J} {K' : GlobalList J}
(hA : AtomSupport atoms r rank)
(hqual : Described atoms K'.Qual 195)
(hcut : Described atoms Stilde 205)
(hhigh : W' \ S = (K'.Qual ∩ B'.pred r) \ A'.weakPred r)
(hlow : W' ∩ S = (((A'.desc r ∩ B.pred r) \ B'.weakDesc r) \ V.weakDesc r) ∩ Stilde) :
Described atoms W' 406 := by
have hh : Described atoms (W' \ S) 197 := by
rw [hhigh]
exact (hqual.inter (hA.pred B')).diff (hA.weakPred A')
have hl : Described atoms (W' ∩ S) 209 := by
rw [hlow]
exact ((((hA.desc A').inter (hA.pred B)).diff (hA.weakDesc B')).diff (hA.weakDesc V)).inter hcut
have he : W' = (W' \ S) ∪ (W' ∩ S) := by ext x; simp only [Set.mem_union, Set.mem_sdiff, Set.mem_inter_iff]; tauto
rw [he]
exact hh.union hl
end DescriptionInterface
end ThreeMachine.Structure
namespace ThreeMachine.Structure
namespace GlobalList
section SameUpdate
variable {J : Type} {K : GlobalList J} {rank : J → ℕ}
noncomputable def sameUpdate (K : GlobalList J) (rank : J → ℕ) (B t : ℕ)
(D P : Set J) : GlobalList J :=
(K.carry rank (t/B) (t%B)).append (D \ P)
end SameUpdate
end GlobalList
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section SameBoundaryUpdate
variable {J : Type} [Fintype J] [DecidableEq J]
end SameBoundaryUpdate
end ThreeMachine.Structure
end
end OAI
end
section
-- module NodeCertificates
namespace OAI
section
namespace ThreeMachine.Structure
section NodeCertificates
variable {J A : Type} [Fintype J] [DecidableEq J]
structure NodeData (r : J → J → Prop) (rank : J → ℕ) (atoms : A → Set J)
(p : Layout J) (W : Set J) where
full : p.Full r
a : ℕ
b : ℕ
left : Boundary J
right : Boundary J
leftAt : left.At p.time (Fintype.card J / 3) a
rightAt : right.At p.time (Fintype.card J / 3) b
window : ∀ x, x ∈ W ↔ x ∈ Window p.time a b
list : GlobalList J
run : RunData list rank atoms W
upsets : list.Upsets r
second_upset : GlobalUpset r run.second
disjoint : list.InjectionDisjoint W
length : list.indices.card ≤ 5
high : ∀ x ∈ W, x ∈ list.Qual → x ∈ right.pred r
low : ∀ x ∈ W, x ∉ list.Qual → x ∈ left.desc r
past : PastInvariant r p.time list left a
swap : SwapInvariant r p W list rank left a
small : Described atoms W 406
reverseSeed : ReverseSeed r p.time atoms W right b
namespace NodeData
variable {r : J → J → Prop} {rank : J → ℕ} {atoms : A → Set J}
{p q : Layout J} {W : Set J}
def reorder (D : NodeData r rank atoms p W) (hfix : p.FixedOutside q W)
(hq : q.Respects r) : NodeData r rank atoms q W :=
{ D with
full := ⟨D.full.1, hq⟩
leftAt := hfix.boundary D.window (Or.inl le_rfl) D.leftAt
rightAt := hfix.boundary D.window (Or.inr le_rfl) D.rightAt
window := hfix.window D.window
past := D.past.reorder hfix D.window
swap := D.swap.reorder hfix
reverseSeed := D.reverseSeed.reorder (Set.ext D.window) hfix }
noncomputable def root (p : Layout J) (hp : p.Full r)
(hA : AtomSupport atoms r rank) : NodeData r rank atoms p Set.univ := by
refine { full := hp, a := 0, b := Fintype.card J / 3 + 1
left := .left, right := .right, leftAt := rfl, rightAt := rfl
window := ?_, list := .one Set.univ, run := RunData.root hA.truth
upsets := ?_, second_upset := ?_, disjoint := ?_, length := ?_
high := ?_, low := ?_, past := ?_, swap := ?_
small := hA.truth.mono (by omega), reverseSeed := ?_ }
· intro x
have := p.time_bounds hp.1 x
simp only [Set.mem_univ, Window, Set.mem_ofPred_eq, true_iff]
omega
· intro i _ x y _ _
trivial
· intro x y _ _
trivial
· intro i hi h2i
simp only [GlobalList.one, Finset.mem_singleton] at hi
omega
· simp [GlobalList.one]
· intro x _ _
trivial
· intro x _ _
trivial
· intro x _ htime
have := (p.time_bounds hp.1 x).1
omega
· intro q _ _ x _ _ y hy
have := (q.time_bounds hp.1 y).1
omega
· refine ⟨Set.univ, ?_, hA.truth.mono (by omega), ?_, ?_⟩
· intro x y _ _
trivial
· intro x _ _
trivial
· intro x _
have := (p.time_bounds hp.1 x).2
omega
end NodeData
structure EdgeData (r : J → J → Prop) (rank : J → ℕ) (atoms : A → Set J)
(p : Layout J) (W : Set J) (a b v ap bp : ℕ)
(B V A' B' : Boundary J) where
full : p.Full r
parent : W = Window p.time a b
endAt : B.At p.time (Fintype.card J / 3) b
centerAt : V.At p.time (Fintype.card J / 3) v
startAt : A'.At p.time (Fintype.card J / 3) ap
targetAt : B'.At p.time (Fintype.card J / 3) bp
targetActual : ∃ Z, B' = Boundary.actual Z
start_le : a ≤ ap
strict : ap < bp
target_le : bp ≤ v
center_lt : v < b
cutoff : Set J
finalCutoff : Set J
finalSmall : Described atoms finalCutoff 1
centerSep : V.Separates r p.time W finalCutoff v
startSep : A'.Separates r p.time (Window p.time a v) cutoff ap
targetSep : B'.Separates r p.time (Window p.time a v) cutoff bp
covers : ∀ x ∈ W, x ∈ cutoff → x ∈ B.pred r
below : ∀ x ∈ W, x ∈ cutoff → x ∈ finalCutoff
list : GlobalList J
run : RunData list rank atoms W
upsets : list.Upsets r
second_upset : GlobalUpset r run.second
disjoint : list.InjectionDisjoint W
labels : ∀ x ∈ W, x ∈ list.Qual ↔ x ∉ cutoff
past : PastInvariant r p.time list A' ap
swap : SwapInvariant r p (Window p.time ap bp) list rank A' ap
globalCutoff : Set J
cutoffSmall : Described atoms globalCutoff 205
cutoffAgrees : ∀ x ∈ W, x ∈ globalCutoff ↔ x ∈ cutoff
lowExtension : Set J
downset : GlobalUpset (fun x y => r y x) lowExtension
lowSmall : Described atoms lowExtension 21
lowAgrees : ∀ x ∈ W, x ∈ lowExtension ↔ x ∈ cutoff
namespace EdgeData
variable {r : J → J → Prop} {rank : J → ℕ} {atoms : A → Set J}
{p : Layout J} {W : Set J} {a b v ap bp : ℕ} {B V A' B' : Boundary J}
noncomputable def toNode
(D : EdgeData r rank atoms p W a b v ap bp B V A' B')
(htrans : ∀ ⦃x y z⦄, r x y → r y z → r x z)
(hA : AtomSupport atoms r rank) :
NodeData r rank atoms p (Window p.time ap bp) := by
let W' := Window p.time ap bp
have hsub : W' ⊆ W := by
intro x hx
rw [D.parent]
exact ⟨D.start_le.trans_lt hx.1, hx.2.trans_le D.target_le |>.trans D.center_lt⟩
have hE : W' ⊆ Window p.time a v := by
intro x hx
exact ⟨D.start_le.trans_lt hx.1, hx.2.trans_le D.target_le⟩
have hhigh : ∀ x ∈ W', x ∉ D.cutoff → x ∈ B'.pred r := by
intro x hx hn
exact D.targetSep.1 x (hE hx) hx.2 hn
have hlow : ∀ x ∈ W', x ∈ D.cutoff → x ∈ A'.desc r ∩ B.pred r := by
intro x hx hS
exact ⟨D.startSep.2 x (hE hx) hx.1 hS, D.covers x (hsub hx) hS⟩
let K' := D.list.prune W'
let R' := D.run.prune hsub
have hqual : ∀ x ∈ W', x ∈ K'.Qual ↔ x ∉ D.cutoff := by
intro x hx
exact (GlobalList.prune_qual D.list hx).trans (D.labels x (hsub hx))
have hlength : K'.indices.card ≤ 5 := by
obtain ⟨Z, hZ⟩ := D.targetActual
apply GlobalList.pruned_length D.upsets D.disjoint (B := Z)
· intro z hz
have ht : p.time z = bp := (show (Boundary.actual Z).At p.time
(Fintype.card J / 3) bp from hZ ▸ D.targetAt).2.2 z |>.mp hz
rw [D.parent]
exact ⟨by have := D.start_le; have := D.strict; omega,
by have := D.target_le; have := D.center_lt; omega⟩
· intro x hx hq
have h := hhigh x hx ((D.labels x (hsub hx)).mp hq)
simpa only [hZ, Boundary.pred, Set.mem_ofPred_eq] using h
have hpast : PastInvariant r p.time K' A' ap := past_prune D.past
have hh := global_high_identity D.full.2 (p.time_bounds D.full.1)
D.startAt D.targetAt hqual hhigh hpast
have hl := global_low_identity D.full.2 (p.time_bounds D.full.1)
D.startAt D.endAt D.targetAt D.centerAt D.start_le D.strict D.target_le D.center_lt
(fun x hx => D.cutoffAgrees x (D.parent ▸ hx))
(fun x hx => D.below x (D.parent ▸ hx))
(D.parent ▸ D.centerSep) D.targetSep hlow
have hsmall : Described atoms W' 406 := global_child_small hA
(R'.qual_small hA hlength) D.cutoffSmall hh hl
have hseedExists := reverse_seed_at_edge htrans D.full.2 (p.time_bounds D.full.1)
D.endAt D.targetAt D.centerAt D.parent rfl rfl D.start_le D.strict D.target_le D.center_lt
hhigh D.covers D.below D.centerSep D.targetSep D.downset D.lowAgrees D.lowSmall
(hA.pred B) (hA.weakDesc B') (hA.weakDesc V)
exact { full := D.full, a := ap, b := bp, left := A', right := B'
leftAt := D.startAt, rightAt := D.targetAt, window := fun _ => Iff.rfl
list := K', run := R', upsets := GlobalList.prune_upsets D.upsets
second_upset := D.second_upset, disjoint := D.disjoint.prune hsub, length := hlength
high := fun x hx hq => hhigh x hx ((hqual x hx).mp hq)
low := fun x hx hn => (hlow x hx (by by_contra h; exact hn ((hqual x hx).mpr h))).1
past := hpast, swap := swap_prune D.swap, small := hsmall, reverseSeed := Classical.choice hseedExists }
end EdgeData
end NodeCertificates
end ThreeMachine.Structure
namespace ThreeMachine.Structure
namespace Boundary
variable {J : Type} {time : J → ℕ} {T s : ℕ}
end Boundary
section SameEdges
variable {J A : Type} [Fintype J] [DecidableEq J]
{r : J → J → Prop} {rank : J → ℕ} {atoms : A → Set J}
{p : Layout J} {W : Set J}
end SameEdges
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section SwitchedEdges
variable {J A : Type} [Fintype J] [DecidableEq J]
structure SwitchSeed (r : J → J → Prop) (time : J → ℕ) (atoms : A → Set J)
(W : Set J) (B : Boundary J) (a : ℕ) where
predicate : Set J
upset : GlobalUpset r predicate
small : Described atoms predicate 24
cover : ∀ x ∈ W, x ∉ B.desc r → x ∈ predicate
later : ∀ x ∈ predicate, a < time x
variable {r : J → J → Prop} {rank : J → ℕ} {atoms : A → Set J}
{p : Layout J} {W : Set J}
def ReverseSeed.toSwitch {B : Boundary J} {b : ℕ}
(D : ReverseSeed r p.time atoms W B b) (hfull : 3 ∣ Fintype.card J)
(hb : b ≤ Fintype.card J / 3 + 1) :
SwitchSeed (fun x y => r y x) p.reverse.time atoms W B.reverse
(Fintype.card J / 3 + 1 - b) := by
refine { predicate := D.predicate, upset := D.downset, small := D.small
cover := ?_, later := ?_ }
· simpa only [Boundary.desc_reverse] using D.cover
· intro x hx
rw [Layout.reverse_time p hfull]
have := D.earlier x hx
have := p.time_bounds hfull x
omega
end SwitchedEdges
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section Centers
variable {J A : Type} [Fintype J] [DecidableEq J]
{r : J → J → Prop} {rank : J → ℕ} {atoms : A → Set J}
{p q : Layout J} {W : Set J}
end Centers
end ThreeMachine.Structure
end
end OAI
end
section
-- module SplitPaths
namespace OAI
section
namespace ThreeMachine.Structure
section SplitGraph
variable {J A : Type}
def RelativeDescription (atoms : A → Set J) (W L : Set J) (k : ℕ) : Prop :=
∃ F, Described atoms F k ∧ L = W ∩ F
structure SplitVertex (r : J → J → Prop) (atoms : A → Set J) (W : Set J) where
left : Set J
middle : Triple J
right : Set J
partition : ∀ x, x ∈ W ↔ x ∈ left ∨ x ∈ middle.val ∨ x ∈ right
left_middle : Disjoint left (middle.val : Set J)
left_right : Disjoint left right
middle_right : Disjoint (middle.val : Set J) right
antichain : ∀ x ∈ middle.val, ∀ y ∈ middle.val, ¬r x y
no_middle_left : ∀ x ∈ middle.val, ∀ y ∈ left, ¬r x y
no_right_left : ∀ x ∈ right, ∀ y ∈ left, ¬r x y
no_right_middle : ∀ x ∈ right, ∀ y ∈ middle.val, ¬r x y
small_left : RelativeDescription atoms W left 10000
small_right : RelativeDescription atoms W right 10000
namespace SplitVertex
variable {r : J → J → Prop} {atoms : A → Set J} {W : Set J}
@[ext] theorem ext {u v : SplitVertex r atoms W}
(hl : u.left = v.left) (hm : u.middle = v.middle) (hr : u.right = v.right) : u = v := by
cases u
cases v
cases hl
cases hm
cases hr
rfl
def reverse (v : SplitVertex r atoms W) : SplitVertex (fun x y => r y x) atoms W :=
{ left := v.right, middle := v.middle, right := v.left
partition := fun x => (v.partition x).trans (by tauto)
left_middle := v.middle_right.symm, left_right := v.left_right.symm
middle_right := v.left_middle.symm
antichain := fun x hx y hy => v.antichain y hy x hx
no_middle_left := fun x hx y hy => v.no_right_middle y hy x hx
no_right_left := fun x hx y hy => v.no_right_left y hy x hx
no_right_middle := fun x hx y hy => v.no_middle_left y hy x hx
small_left := v.small_right, small_right := v.small_left }
@[simp] theorem reverse_reverse (v : SplitVertex r atoms W) : v.reverse.reverse = v := by
apply ext <;> rfl
def AtTime (v : SplitVertex r atoms W) (time : J → ℕ) (s : ℕ) : Prop :=
(∀ x, x ∈ v.left ↔ x ∈ W ∧ time x < s) ∧
(∀ x, x ∈ v.middle.val ↔ x ∈ W ∧ time x = s) ∧
(∀ x, x ∈ v.right ↔ x ∈ W ∧ s < time x)
theorem left_subset (v : SplitVertex r atoms W) : v.left ⊆ W :=
fun x hx => (v.partition x).mpr (Or.inl hx)
theorem right_subset (v : SplitVertex r atoms W) : v.right ⊆ W :=
fun x hx => (v.partition x).mpr (Or.inr (Or.inr hx))
theorem right_eq (v : SplitVertex r atoms W) : v.right = W \ (v.left ∪ v.middle.val) := by
ext x
have hlm := Set.disjoint_left.mp v.left_middle
have hlr := Set.disjoint_left.mp v.left_right
have hmr := Set.disjoint_left.mp v.middle_right
constructor
· intro hx
exact ⟨v.right_subset hx, fun h => h.elim (fun hl => hlr hl hx) (fun hm => hmr hm hx)⟩
· rintro ⟨hx, hn⟩
rcases (v.partition x).mp hx with hl | hm | hr
· exact (hn (Or.inl hl)).elim
· exact (hn (Or.inr hm)).elim
· exact hr
def Step (P : Set J → Prop) (u v : SplitVertex r atoms W) : Prop :=
u.left ∪ u.middle.val ⊆ v.left ∧ P (v.left \ (u.left ∪ u.middle.val))
end SplitVertex
def AcceptedAt (r : J → J → Prop) (atoms : A → Set J) : ℕ → Set J → Prop
| 0, W => Described atoms W 10000 ∧ W = ∅
| n+1, W => Described atoms W 10000 ∧ (W = ∅ ∨
∃ u v : SplitVertex r atoms W, AcceptedAt r atoms n u.left ∧
Relation.ReflTransGen (SplitVertex.Step (AcceptedAt r atoms n)) u v ∧
AcceptedAt r atoms n v.right)
namespace AcceptedAt
variable {r : J → J → Prop} {atoms : A → Set J}
end AcceptedAt
end SplitGraph
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section TemporalSplits
variable {J A : Type} [Fintype J] {r : J → J → Prop} {rank : J → ℕ}
{atoms : A → Set J} {p q : Layout J} {W : Set J}
omit [Fintype J] in
theorem before_small (hA : AtomSupport atoms r rank) {H : Set J} {k : ℕ}
(hH : Described atoms H k) (B : Boundary J) :
Described atoms (B.before r H) (k+2) := by
have h := (hA.pred B).union (hH.diff (hA.weakDesc B))
simpa only [Boundary.before, Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using h
noncomputable def SplitVertex.ofTime {a b s k : ℕ} {Z : Triple J} {F : Set J}
(hp : p.Full r) (hW : ∀ x, x ∈ W ↔ x ∈ Window p.time a b)
(hs : a < s ∧ s < b) (hZ : (Boundary.actual Z).At p.time (Fintype.card J / 3) s)
(hF : Described atoms F k) (hk : k+1 ≤ 10000)
(hZA : Described atoms (Z.val : Set J) 1)
(hbefore : ∀ x ∈ W, x ∈ F ↔ p.time x < s) : SplitVertex r atoms W := by
let L : Set J := {x | x ∈ W ∧ p.time x < s}
let R : Set J := {x | x ∈ W ∧ s < p.time x}
have hZm : ∀ x, x ∈ Z.val ↔ x ∈ W ∧ p.time x = s := by
intro x
rw [hZ.2.2 x]
constructor
· intro hx
exact ⟨(hW x).mpr ⟨by omega, by omega⟩, hx⟩
· exact And.right
refine {
left := L, middle := Z, right := R
partition := ?_, left_middle := ?_, left_right := ?_, middle_right := ?_
antichain := ?_, no_middle_left := ?_, no_right_left := ?_, no_right_middle := ?_
small_left := ?_, small_right := ?_ }
· intro x
change x ∈ W ↔ (x ∈ W ∧ p.time x < s) ∨ x ∈ Z.val ∨ (x ∈ W ∧ s < p.time x)
rw [hZm x]
constructor
· intro hx
rcases lt_trichotomy (p.time x) s with h | h | h
· exact Or.inl ⟨hx, h⟩
· exact Or.inr (Or.inl ⟨hx, h⟩)
· exact Or.inr (Or.inr ⟨hx, h⟩)
· tauto
· apply Set.disjoint_left.mpr
intro x hx hm
have := (hZm x).mp hm
exact (ne_of_lt hx.2) this.2
· apply Set.disjoint_left.mpr
intro x hx hy
exact (not_lt_of_ge hx.2.le) hy.2
· apply Set.disjoint_left.mpr
intro x hm hr
have := (hZm x).mp hm
exact (ne_of_gt hr.2) this.2
· intro x hx y hy hxy
have := (hZ.2.2 x).mp hx
have := (hZ.2.2 y).mp hy
have := hp.2 x y hxy
omega
· intro x hx y hy hxy
have := (hZ.2.2 x).mp hx
have := hy.2
have := hp.2 x y hxy
omega
· intro x hx y hy hxy
have := hx.2
have := hy.2
have := hp.2 x y hxy
omega
· intro x hx y hy hxy
have := hx.2
have := (hZ.2.2 y).mp hy
have := hp.2 x y hxy
omega
· refine ⟨F, hF.mono (by omega), ?_⟩
ext x
change (x ∈ W ∧ p.time x < s) ↔ x ∈ W ∧ x ∈ F
exact and_congr_right (fun hx => (hbefore x hx).symm)
· refine ⟨Fᶜ \ (Z.val : Set J), (hF.compl.diff hZA).mono hk, ?_⟩
ext x
change (x ∈ W ∧ s < p.time x) ↔ x ∈ W ∧ x ∉ F ∧ x ∉ Z.val
rw [hZ.2.2 x]
constructor
· rintro ⟨hx, ht⟩
exact ⟨hx, fun h => (not_lt_of_ge ht.le) ((hbefore x hx).mp h), (ne_of_gt ht)⟩
· rintro ⟨hx, hn, he⟩
have ht : ¬p.time x < s := fun h => hn ((hbefore x hx).mpr h)
exact ⟨hx, by omega⟩
theorem EdgeData.target_description [DecidableEq J]
{a b v ap bp : ℕ} {B V A' B' : Boundary J}
(D : EdgeData r rank atoms p W a b v ap bp B V A' B')
(hA : AtomSupport atoms r rank) (hFinal : Described atoms D.finalCutoff 1) :
∃ F, Described atoms F 210 ∧ ∀ x ∈ W, x ∈ F ↔ p.time x < bp := by
let F := V.before r D.finalCutoff ∩ B'.before r D.globalCutoff
refine ⟨F, ?_, ?_⟩
· exact (before_small hA hFinal V).inter (before_small hA D.cutoffSmall B')
· intro x hx
have hW : a < p.time x ∧ p.time x < b :=
show x ∈ Window p.time a b from D.parent ▸ hx
have hc := Boundary.separates_description D.full.2 (p.time_bounds D.full.1)
D.centerAt D.centerSep (fun _ _ => Iff.rfl) x hx
change x ∈ V.before r D.finalCutoff ∧ x ∈ B'.before r D.globalCutoff ↔ p.time x < bp
constructor
· rintro ⟨hv, hb⟩
have hxE : x ∈ Window p.time a v := ⟨hW.1, hc.mp hv⟩
exact (Boundary.separates_description D.full.2 (p.time_bounds D.full.1)
D.targetAt D.targetSep (fun y hy => D.cutoffAgrees y (D.parent.symm ▸
show y ∈ Window p.time a b from ⟨hy.1, hy.2.trans D.center_lt⟩)) x hxE).mp hb
· intro ht
have hxE : x ∈ Window p.time a v := ⟨hW.1, ht.trans_le D.target_le⟩
refine ⟨hc.mpr hxE.2, ?_⟩
exact (Boundary.separates_description D.full.2 (p.time_bounds D.full.1)
D.targetAt D.targetSep (fun y hy => D.cutoffAgrees y (D.parent.symm ▸
show y ∈ Window p.time a b from ⟨hy.1, hy.2.trans D.center_lt⟩)) x hxE).mpr ht
noncomputable def EdgeData.targetVertex [DecidableEq J]
{a b v ap bp : ℕ} {B V A' B' : Boundary J}
(D : EdgeData r rank atoms p W a b v ap bp B V A' B')
(hA : AtomSupport atoms r rank) (hFinal : Described atoms D.finalCutoff 1) :
SplitVertex r atoms W := by
let Z := Classical.choose D.targetActual
have hZ : B' = Boundary.actual Z := Classical.choose_spec D.targetActual
let F := Classical.choose (D.target_description hA hFinal)
have hF := Classical.choose_spec (D.target_description hA hFinal)
exact SplitVertex.ofTime D.full (fun x => D.parent ▸ Iff.rfl)
⟨D.start_le.trans_lt D.strict, D.target_le.trans_lt D.center_lt⟩
(hZ ▸ D.targetAt) hF.1 (by omega) (hA.triple Z) hF.2
end TemporalSplits
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section PrefixPaths
variable {J A : Type} [Fintype J] {r : J → J → Prop} {rank : J → ℕ}
{atoms : A → Set J} {p q : Layout J} {W : Set J} {P : Set J → Prop}
def Reached (P : Set J → Prop) (r : J → J → Prop) (atoms : A → Set J)
(W : Set J) (time : J → ℕ) (a s : ℕ) : Prop :=
s = a ∨ ∃ u v : SplitVertex r atoms W, P u.left ∧
Relation.ReflTransGen (SplitVertex.Step P) u v ∧ v.AtTime time s
end PrefixPaths
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section WalkPaths
variable {J A : Type} [Fintype J] {r : J → J → Prop} {rank : J → ℕ}
{atoms : A → Set J} {p : Layout J} {W : Set J} {P : Set J → Prop}
end WalkPaths
end ThreeMachine.Structure
end
end OAI
end
section
-- module HierarchyCompleteness
namespace OAI
section
namespace ThreeMachine.Structure
section SamePaths
variable {J A : Type} [Fintype J] [DecidableEq J]
{r : J → J → Prop} {rank : J → ℕ} {atoms : A → Set J}
{p : Layout J} {W : Set J} {P : Set J → Prop}
end SamePaths
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section SwitchPaths
variable {J A : Type} [Fintype J] [DecidableEq J]
{r : J → J → Prop} {rank : J → ℕ} {atoms : A → Set J}
{p q : Layout J} {W : Set J} {P : Set J → Prop}
omit [DecidableEq J] in
def SwitchSeed.reorder {L : Boundary J} {a b : ℕ}
(G : SwitchSeed r p.time atoms W L a)
(hW : ∀ x, x ∈ W ↔ x ∈ Window p.time a b) (hfix : p.FixedOutside q W) :
SwitchSeed r q.time atoms W L a := by
refine { G with later := ?_ }
intro x hx
by_cases hxW : x ∈ W
· exact ((hfix.window hW x).mp hxW).1
· rw [hfix.time hxW]
exact G.later x hx
end SwitchPaths
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section SideNormalization
variable {J A : Type} [Fintype J] [DecidableEq J]
{r : J → J → Prop} {rank : J → ℕ} {atoms : A → Set J}
{p : Layout J} {W : Set J} {P : Set J → Prop}
end SideNormalization
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section ReversePaths
variable {J A : Type} [Fintype J] {r : J → J → Prop}
{atoms : A → Set J} {p : Layout J} {W S : Set J}
end ReversePaths
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section Completeness
variable {J A : Type} [Fintype J] [DecidableEq J] {atoms : A → Set J}
end Completeness
end ThreeMachine.Structure
end
end OAI
end
section
-- module HierarchySoundness
namespace OAI
section
namespace ThreeMachine.Structure
section Soundness
variable {J A : Type} [Fintype J] {r : J → J → Prop} {atoms : A → Set J}
structure FullBlock (r : J → J → Prop) (W : Set J) where
length : ℕ
time : J → ℕ
bounds : ∀ x ∈ W, 1 ≤ time x ∧ time x ≤ length
capacity : ∀ t, {x | x ∈ W ∧ time x = t}.ncard ≤ 3
respects : ∀ x ∈ W, ∀ y ∈ W, r x y → time x < time y
size : W.ncard = 3 * length
namespace FullBlock
variable {U V W : Set J}
def empty : FullBlock r (∅ : Set J) where
length := 0
time := fun _ => 0
bounds := by simp
capacity := by simp
respects := by simp
size := by simp
def triple (Z : Triple J) (hZ : ∀ x ∈ Z.val, ∀ y ∈ Z.val, ¬r x y) :
FullBlock r (Z.val : Set J) where
length := 1
time := fun _ => 1
bounds := by simp
capacity := fun _ => (Set.ncard_le_ncard (fun _ hx => hx.1)).trans (by simpa using Z.property.le)
respects := fun x hx y hy h => (hZ x hx y hy h).elim
size := by simpa using Z.property
noncomputable def append (s : FullBlock r U) (t : FullBlock r V)
(hd : Disjoint U V) (hback : ∀ x ∈ V, ∀ y ∈ U, ¬r x y) :
FullBlock r (U ∪ V) := by
classical
let time : J → ℕ := fun x => if x ∈ U then s.time x else s.length + t.time x
have htimeU (x : J) (hx : x ∈ U) : time x = s.time x := ite_eq_left hx
have htimeV (x : J) (hx : x ∈ V) : time x = s.length + t.time x :=
ite_eq_right (fun hu => Set.disjoint_left.mp hd hu hx)
refine ⟨s.length + t.length, time, ?_, ?_, ?_, ?_⟩
· intro x hx
rcases hx with hx | hx
· rw [htimeU x hx]
have := s.bounds x hx
omega
· rw [htimeV x hx]
have := t.bounds x hx
omega
· intro k
by_cases hk : k ≤ s.length
· have he : {x | x ∈ U ∪ V ∧ time x = k} = {x | x ∈ U ∧ s.time x = k} := by
ext x
constructor
· rintro ⟨hx | hx, he⟩
· exact ⟨hx, (htimeU x hx).symm.trans he⟩
· rw [htimeV x hx] at he
have := t.bounds x hx
omega
· rintro ⟨hx, he⟩
exact ⟨Or.inl hx, (htimeU x hx).trans he⟩
rw [he]
exact s.capacity k
· have he : {x | x ∈ U ∪ V ∧ time x = k} =
{x | x ∈ V ∧ t.time x = k - s.length} := by
ext x
constructor
· rintro ⟨hx | hx, he⟩
· rw [htimeU x hx] at he
have := s.bounds x hx
omega
· rw [htimeV x hx] at he
exact ⟨hx, by omega⟩
· rintro ⟨hx, he⟩
refine ⟨Or.inr hx, ?_⟩
rw [htimeV x hx, he]
omega
rw [he]
exact t.capacity (k-s.length)
· intro x hx y hy hxy
rcases hx with hx | hx <;> rcases hy with hy | hy
· simpa only [htimeU x hx, htimeU y hy] using s.respects x hx y hy hxy
· rw [htimeU x hx, htimeV y hy]
have := s.bounds x hx
have := t.bounds y hy
omega
· exact (hback x hx y hy hxy).elim
· simpa only [htimeV x hx, htimeV y hy, Nat.add_lt_add_iff_left] using
t.respects x hx y hy hxy
· rw [Set.ncard_union_eq hd, s.size, t.size, Nat.mul_add]
end FullBlock
namespace SplitVertex
variable {W : Set J} {u v : SplitVertex r atoms W}
omit [Fintype J] in
theorem gap_subset_right (_huv : u.left ∪ u.middle.val ⊆ v.left) :
v.left \ (u.left ∪ u.middle.val) ⊆ u.right := by
intro x hx
rw [u.right_eq]
exact ⟨v.left_subset hx.1, hx.2⟩
omit [Fintype J] in
theorem left_union_gap (huv : u.left ∪ u.middle.val ⊆ v.left) :
(u.left ∪ u.middle.val) ∪ (v.left \ (u.left ∪ u.middle.val)) = v.left := by
ext x
constructor
· intro hx
exact hx.elim (fun h => huv h) (fun h => h.1)
· intro hx
by_cases hu : x ∈ u.left ∪ u.middle.val
· exact Or.inl hu
· exact Or.inr ⟨hx, hu⟩
noncomputable def add_middle (v : SplitVertex r atoms W) (s : FullBlock r v.left) :
FullBlock r (v.left ∪ v.middle.val) :=
s.append (FullBlock.triple v.middle v.antichain) v.left_middle v.no_middle_left
noncomputable def advance (s : FullBlock r u.left)
(huv : u.left ∪ u.middle.val ⊆ v.left)
(t : FullBlock r (v.left \ (u.left ∪ u.middle.val))) : FullBlock r v.left := by
have hd : Disjoint (u.left ∪ u.middle.val) (v.left \ (u.left ∪ u.middle.val)) := by
exact Set.disjoint_left.mpr (fun _ hx hy => hy.2 hx)
have hback : ∀ x ∈ v.left \ (u.left ∪ u.middle.val),
∀ y ∈ u.left ∪ u.middle.val, ¬r x y := by
intro x hx y hy
have hxr := gap_subset_right huv hx
exact hy.elim (u.no_right_left x hxr y) (u.no_right_middle x hxr y)
exact left_union_gap huv ▸ (u.add_middle s).append t hd hback
noncomputable def finish (v : SplitVertex r atoms W)
(s : FullBlock r v.left) (t : FullBlock r v.right) : FullBlock r W := by
have hd : Disjoint (v.left ∪ v.middle.val) v.right := v.left_right.union_left v.middle_right
have hback : ∀ x ∈ v.right, ∀ y ∈ v.left ∪ v.middle.val, ¬r x y := by
intro x hx y hy
exact hy.elim (v.no_right_left x hx y) (v.no_right_middle x hx y)
have he : (v.left ∪ v.middle.val) ∪ v.right = W := by
ext x
simpa only [Set.mem_union, Finset.mem_coe, or_assoc] using (v.partition x).symm
exact he ▸ (v.add_middle s).append t hd hback
end SplitVertex
end Soundness
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section AtomicFamily
variable {J : Type} [Fintype J]
inductive Atomic (J : Type) [Fintype J]
| constant (value : Bool)
| threshold (frame upper : Bool) (k : Fin (Fintype.card J + 2))
| cone (frame : Bool) (kind : Fin 5) (Z : Triple J)
deriving Fintype
namespace Atomic
def eval (r : J → J → Prop) (rank reverseRank : J → ℕ) : Atomic J → Set J
| .constant b => if b then Set.univ else ∅
| .threshold frame upper k =>
let ρ := if frame then reverseRank else rank
if upper then {x | ρ x ≤ k.val} else {x | k.val ≤ ρ x}
| .cone frame kind Z =>
let R := if frame then (fun x y => r y x) else r
match kind.val with
| 0 => Z.val
| 1 => (Boundary.actual Z).pred R
| 2 => (Boundary.actual Z).desc R
| 3 => (Boundary.actual Z).weakPred R
| _ => (Boundary.actual Z).weakDesc R
end Atomic
end AtomicFamily
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section Ranks
variable {J K : Type} [Fintype J] [LinearOrder K]
def rankOfKey (key : J → K) (x : J) : ℕ :=
(Finset.univ.filter (fun y => key y < key x)).card + 1
end Ranks
section IndexedRanks
variable {n : ℕ} (r : Fin n → Fin n → Prop) [DecidableRel r]
def predecessorCount (x : Fin n) : ℕ := (Finset.univ.filter (fun y => r y x)).card
def jobKey (x : Fin n) : Lex (ℕ × Fin n) := toLex (predecessorCount r x, x)
def jobRank : Fin n → ℕ := rankOfKey (jobKey r)
def reverseJobRank (x : Fin n) : ℕ := n+1-jobRank r x
end IndexedRanks
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section ScheduleLayouts
variable {J : Type} [Fintype J]
end ScheduleLayouts
end ThreeMachine.Structure
end
end OAI
end
section
-- module Padding
namespace OAI
section
namespace ThreeMachine
def Instance.order {n : ℕ} (G : Instance n) : Fin n → Fin n → Prop := Relation.TransGen G.edge
def paddedOrder {n : ℕ} (r : Fin n → Fin n → Prop) (m : ℕ) (u v : Fin m) : Prop :=
∃ x y : Fin n, u.val = x.val ∧ v.val = y.val ∧ r x y
namespace Structure
end Structure
end ThreeMachine
end
end OAI
end
section
-- module EffectiveFamily
namespace OAI
section
namespace ThreeMachine.Structure
namespace Formula
variable {A B C : Type}
def map (f : A → B) : Formula A → Formula B
| .leaf a s => .leaf (f a) s
| .conj p q => .conj (p.map f) (q.map f)
| .disj p q => .disj (p.map f) (q.map f)
@[simp] theorem leaves_map (f : A → B) (p : Formula A) : (p.map f).leaves = p.leaves := by
induction p with
| leaf => rfl
| conj p q hp hq | disj p q hp hq => simp only [map, leaves, hp, hq]
@[simp] theorem map_comp (f : A → B) (g : B → C) (p : Formula A) :
(p.map f).map g = p.map (g ∘ f) := by
induction p with
| leaf => rfl
| conj p q hp hq | disj p q hp hq => simp only [map, hp, hq]
@[simp] theorem map_id (p : Formula A) : p.map id = p := by
induction p with
| leaf => rfl
| conj p q hp hq | disj p q hp hq => simp only [map, hp, hq]
def depthEnum (alphabet : List A) : ℕ → List (Formula A)
| 0 => []
| n+1 => alphabet.flatMap (fun a => [.leaf a false, .leaf a true]) ++
(depthEnum alphabet n).flatMap (fun p =>
(depthEnum alphabet n).flatMap (fun q => [.conj p q, .disj p q]))
def templates (K : ℕ) : List (Formula (Fin K)) :=
(depthEnum (List.finRange K) K).filter (fun p => p.leaves ≤ K)
end Formula
def assignments {A : Type} (alphabet : List A) : (k : ℕ) → List (Fin k → A)
| 0 => [Fin.elim0]
| k+1 => alphabet.flatMap (fun a => (assignments alphabet k).map (Fin.cons a))
end ThreeMachine.Structure
namespace ThreeMachine.Structure
section EffectiveAlphabet
variable {J : Type} [Fintype J] [DecidableEq J]
def tripleList (jobs : List J) : List (Triple J) :=
(jobs.flatMap (fun a => jobs.flatMap (fun b => jobs.map (fun c => ({a,b,c} : Finset J))))).filterMap
(fun Z => if h : Z.card = 3 then some ⟨Z, h⟩ else none)
def Atomic.alphabet (jobs : List J) : List (Atomic J) :=
[.constant false, .constant true] ++
[false,true].flatMap (fun frame => [false,true].flatMap (fun upper =>
(List.finRange (Fintype.card J + 2)).map (.threshold frame upper))) ++
[false,true].flatMap (fun frame => (List.finRange 5).flatMap (fun kind =>
(tripleList jobs).map (.cone frame kind)))
end EffectiveAlphabet
end ThreeMachine.Structure
end
end OAI
end
section
-- module DynamicProgram
namespace OAI
section
namespace ThreeMachine.Algorithm
open Structure
structure Block (J : Type) where
length : ℕ
time : J → ℕ
namespace Block
variable {J : Type} [Fintype J] [DecidableEq J] {r : J → J → Prop}
def Valid (r : J → J → Prop) (W : Finset J) (s : Block J) : Prop :=
∃ b : FullBlock r (W : Set J), b.length = s.length ∧ b.time = s.time
def empty : Block J := ⟨0, fun _ => 0⟩
def triple : Block J := ⟨1, fun _ => 1⟩
def append (U : Finset J) (s t : Block J) : Block J :=
⟨s.length + t.length, fun x => if x ∈ U then s.time x else s.length + t.time x⟩
end Block
structure State (J : Type) where
left : Finset J
middle : Finset J
right : Finset J
deriving DecidableEq
namespace State
variable {J : Type} [Fintype J] [DecidableEq J] {r : J → J → Prop}
def candidate (W F Z : Finset J) : State J :=
⟨W ∩ F, Z, W \ ((W ∩ F) ∪ Z)⟩
def Compatible (r : J → J → Prop) (W : Finset J) (s : State J) : Prop :=
(s.left ∪ s.middle) ∪ s.right = W ∧
Disjoint s.left s.middle ∧ Disjoint s.left s.right ∧ Disjoint s.middle s.right ∧
s.middle.card = 3 ∧
(∀ x ∈ s.middle, ∀ y ∈ s.middle, ¬r x y) ∧
(∀ x ∈ s.middle, ∀ y ∈ s.left, ¬r x y) ∧
(∀ x ∈ s.right, ∀ y ∈ s.left, ¬r x y) ∧
(∀ x ∈ s.right, ∀ y ∈ s.middle, ¬r x y)
instance [DecidableRel r] (W : Finset J) (s : State J) : Decidable (s.Compatible r W) :=
inferInstanceAs (Decidable (_ ∧ _ ∧ _ ∧ _ ∧ _ ∧ _ ∧ _ ∧ _ ∧ _))
def upto (s : State J) : Finset J := s.left ∪ s.middle
def advance (u : State J) (s t : Block J) : Block J :=
Block.append u.upto (Block.append u.left s Block.triple) t
def finish (u : State J) (s t : Block J) : Block J := advance u s t
end State
end ThreeMachine.Algorithm
namespace ThreeMachine.Algorithm
def lookup {K V : Type} [DecidableEq K] : List (K × V) → K → Option V
| [], _ => none
| (a,b)::xs, k => if a = k then some b else lookup xs k
def Has {K V : Type} [DecidableEq K] (tab : List (K × V)) (k : K) : Prop :=
∃ v, lookup tab k = some v
def firstResult {K V : Type} (f : K → Option V) : List K → Option V
| [] => none
| k::ks => match f k with
| some v => some v
| none => firstResult f ks
def tableOf {K V : Type} (ks : List K) (f : K → Option V) : List (K × V) :=
ks.filterMap (fun k => (f k).map (fun v => (k,v)))
inductive Walk {K : Type} (r : K → K → Prop) : ℕ → K → K → Prop
| refl (a : K) : Walk r 0 a a
| tail {n a b c} : Walk r n a b → r b c → Walk r (n+1) a c
namespace Walk
variable {K : Type} {r : K → K → Prop}
end Walk
end ThreeMachine.Algorithm
namespace ThreeMachine.Algorithm
open Structure
section DynamicProgram
variable {J : Type} [Fintype J] [DecidableEq J] (r : J → J → Prop) [DecidableRel r]
def states (family triples : List (Finset J)) (W : Finset J) : List (State J) :=
(family.flatMap (fun F => triples.map (State.candidate W F))).filter (fun s => s.Compatible r W)
def tryAdvance (tab : List (Finset J × Block J)) (u : State J × Block J)
(v : State J) : Option (Block J) :=
if u.1.upto ⊆ v.left then (lookup tab (v.left \ u.1.upto)).map (u.1.advance u.2) else none
def expand (tab : List (Finset J × Block J)) (sts : List (State J))
(marks : List (State J × Block J)) : List (State J × Block J) :=
tableOf sts (fun v => match lookup marks v with
| some s => some s
| none => firstResult (fun u => tryAdvance tab u v) marks)
def markings (tab : List (Finset J × Block J)) (sts : List (State J)) :
ℕ → List (State J × Block J)
| 0 => tableOf sts (fun v => lookup tab v.left)
| k+1 => expand tab sts (markings tab sts k)
def solve (tab : List (Finset J × Block J)) (family triples : List (Finset J))
(W : Finset J) : Option (Block J) :=
if W = ∅ then some Block.empty else
firstResult (fun v => (lookup tab v.1.right).map (v.1.finish v.2))
(markings tab (states r family triples W) (Fintype.card J))
def layers (family triples : List (Finset J)) : ℕ → List (Finset J × Block J)
| 0 => [(∅, Block.empty)]
| k+1 => tableOf family (solve r (layers family triples k) family triples)
def TableGood (tab : List (Finset J × Block J)) : Prop :=
∀ W s, (W,s) ∈ tab → s.Valid r W
def MarksGood (W : Finset J) (marks : List (State J × Block J)) : Prop :=
∀ u s, (u,s) ∈ marks → u.Compatible r W ∧ s.Valid r u.left
def Arc (tab : List (Finset J × Block J)) (sts : List (State J)) (u v : State J) : Prop :=
u ∈ sts ∧ v ∈ sts ∧ u.upto ⊆ v.left ∧ Has tab (v.left \ u.upto)
end DynamicProgram
end ThreeMachine.Algorithm
namespace ThreeMachine.Algorithm
open Structure
open scoped Classical
section EraseSplits
variable {J A : Type} [Fintype J] [DecidableEq J] {r : J → J → Prop}
{atoms : A → Set J} {W : Set J}
omit [Fintype J] [DecidableEq J] in
@[ext] theorem State.ext {u v : State J} (hL : u.left = v.left)
(hM : u.middle = v.middle) (hR : u.right = v.right) : u = v := by
cases u
cases v
cases hL
cases hM
cases hR
rfl
noncomputable def State.erase (v : SplitVertex r atoms W) : State J :=
⟨v.left.toFinset, v.middle.val, v.right.toFinset⟩
end EraseSplits
section Completeness
variable {J A : Type} [Fintype J] [DecidableEq J] (r : J → J → Prop) [DecidableRel r]
(atoms : A → Set J) (family triples : List (Finset J))
(hfamily : ∀ F, Described atoms F 10000 → F.toFinset ∈ family)
(htriples : ∀ Z : Triple J, Z.val ∈ triples)
end Completeness
end ThreeMachine.Algorithm
end
end OAI
end
section
-- module SchedulingAlgorithm
namespace OAI
section
namespace ThreeMachine.Algorithm
section Closure
variable {n : ℕ}
def closureStep (E R : Finset (Fin n × Fin n)) : Finset (Fin n × Fin n) :=
R ∪ Finset.univ.filter (fun p => ∃ v : Fin n, (p.1,v) ∈ R ∧ (v,p.2) ∈ E)
def closureTable (G : Instance n) (k : ℕ) : Finset (Fin n × Fin n) :=
(closureStep G.edges.toFinset)^[k] G.edges.toFinset
def reachable (G : Instance n) (x y : Fin n) : Prop := (x,y) ∈ closureTable G n
instance (G : Instance n) : DecidableRel (reachable G) := fun x y =>
inferInstanceAs (Decidable ((x,y) ∈ closureTable G n))
@[simp] theorem closureTable_zero (G : Instance n) : closureTable G 0 = G.edges.toFinset := rfl
@[simp] theorem closureTable_succ (G : Instance n) (k : ℕ) :
closureTable G (k+1) = closureStep G.edges.toFinset (closureTable G k) :=
Function.iterate_succ_apply' _ _ _
end Closure
end ThreeMachine.Algorithm
namespace ThreeMachine.Structure
section EffectiveFamily
variable {J : Type} [Fintype J] [DecidableEq J]
def Atomic.finsetEval (r : J → J → Prop) [DecidableRel r]
(rank reverseRank : J → ℕ) : Atomic J → Finset J
| .constant b => if b then Finset.univ else ∅
| .threshold frame upper k =>
let ρ := if frame then reverseRank else rank
Finset.univ.filter (fun x => if upper then ρ x ≤ k.val else k.val ≤ ρ x)
| .cone frame kind Z =>
let R := fun x y => if frame then r y x else r x y
letI : DecidableRel R := fun x y => inferInstanceAs (Decidable (if frame then r y x else r x y))
match kind.val with
| 0 => Z.val
| 1 => Finset.univ.filter (fun x => ∃ y ∈ Z.val, R x y)
| 2 => Finset.univ.filter (fun x => ∃ y ∈ Z.val, R y x)
| 3 => (Finset.univ.filter (fun x => ∃ y ∈ Z.val, R x y)) ∪ Z.val
| _ => (Finset.univ.filter (fun x => ∃ y ∈ Z.val, R y x)) ∪ Z.val
theorem Atomic.coe_finsetEval (r : J → J → Prop) [DecidableRel r]
(rank reverseRank : J → ℕ) (a : Atomic J) :
(finsetEval r rank reverseRank a : Set J) = eval r rank reverseRank a := by
cases a with
| constant b => cases b <;> simp [finsetEval,eval]
| threshold frame upper k =>
cases frame <;> cases upper <;> ext x <;> simp [finsetEval,eval]
| cone frame kind Z =>
fin_cases kind <;> cases frame <;> ext x <;>
simp [finsetEval,eval,Boundary.pred,Boundary.desc,Boundary.weakPred,Boundary.weakDesc]
instance Atomic.decideEval (r : J → J → Prop) [DecidableRel r]
(rank reverseRank : J → ℕ) (a : Atomic J) : DecidablePred (eval r rank reverseRank a) :=
fun x => decidable_of_iff (x ∈ finsetEval r rank reverseRank a) (by
change x ∈ (finsetEval r rank reverseRank a : Set J) ↔ _
rw [coe_finsetEval]
rfl)
def Formula.evalFinset {A : Type} (atoms : A → Finset J) : Formula A → Finset J
| .leaf a b => if b then (atoms a)ᶜ else atoms a
| .conj p q => p.evalFinset atoms ∩ q.evalFinset atoms
| .disj p q => p.evalFinset atoms ∪ q.evalFinset atoms
def effectiveFamily (r : J → J → Prop) [DecidableRel r]
(rank reverseRank : J → ℕ) (jobs : List J) (K : ℕ) : List (Finset J) :=
(assignments (Atomic.alphabet jobs) K).flatMap (fun f =>
(Formula.templates K).map (fun s =>
(s.map f).evalFinset (fun a => Finset.univ.filter (Atomic.eval r rank reverseRank a))))
end EffectiveFamily
end ThreeMachine.Structure
namespace ThreeMachine
instance {n m : ℕ} (r : Fin n → Fin n → Prop) [DecidableRel r] :
DecidableRel (paddedOrder r m) := fun x y =>
inferInstanceAs (Decidable (∃ a b : Fin n, x.val = a.val ∧ y.val = b.val ∧ r a b))
end ThreeMachine
namespace ThreeMachine.Algorithm
open Structure
def fullSolve {m : ℕ} (r : Fin m → Fin m → Prop) [DecidableRel r] : Option (Block (Fin m)) :=
lookup (layers r
(effectiveFamily r (jobRank r) (reverseJobRank r) (List.finRange m) 10000)
((tripleList (List.finRange m)).map Subtype.val) m) Finset.univ
def scheduleAt {n : ℕ} (G : Instance n) (T : ℕ) : Option (Fin n → ℕ) :=
if hn : n ≤ 3*T then
(fullSolve (paddedOrder (reachable G) (3*T))).map
(fun s x => s.time (Fin.castLE hn x))
else none
end ThreeMachine.Algorithm
namespace ThreeMachine.Algorithm
open Structure
def best {n : ℕ} (G : Instance n) : ℕ → Option (ℕ × (Fin n → ℕ))
| 0 => none
| k+1 => match best G k with
| some a => some a
| none => (scheduleAt G (k+1)).map (fun time => (k+1,time))
def BestSpec {n : ℕ} (G : Instance n) (k : ℕ) : Option (ℕ × (Fin n → ℕ)) → Prop
| none => ∀ T, 1 ≤ T → T ≤ k → ¬∃ time, Feasible G T time
| some (T,time) => 1 ≤ T ∧ T ≤ k ∧ Feasible G T time ∧
∀ T' time', 1 ≤ T' → T' ≤ k → Feasible G T' time' → T ≤ T'
def output {n : ℕ} (G : Instance n) : Option ℕ → List Bool
| some T => encodeAnswer ((scheduleAt G T).map slots)
| none => encodeAnswer ((best G n).map (fun a => slots a.2))
end ThreeMachine.Algorithm
end
end OAI
end
section
-- module StackMachine
namespace OAI
section
namespace ThreeMachine.StackCompiler
inductive Action
| stay
| pop
| push (b : Bool)
deriving DecidableEq, Fintype
def Action.apply : Action → List Bool → List Bool
| .stay, xs => xs
| .pop, xs => xs.tail
| .push b, xs => b :: xs
abbrev Store (k : ℕ) := Fin (k+1) → List Bool
abbrev Heads (k : ℕ) := Fin (k+1) → Option Bool
abbrev Actions (k : ℕ) := Fin (k+1) → Action
structure Program (k : ℕ) (Q : Type) where
initial : Q
transition : Q → Heads k → Option (Q × Actions k)
structure State (k : ℕ) (Q : Type) where
control : Q
store : Store k
def Program.step {k Q} (P : Program k Q) (c : State k Q) : Option (State k Q) := do
let (q,a) ← P.transition c.control (fun i => (c.store i).head?)
return ⟨q, fun i => (a i).apply (c.store i)⟩
def Program.run {k Q} (P : Program k Q) (s : Store k) (t : ℕ) : State k Q :=
(fun c => (P.step c).getD c)^[t] ⟨P.initial,s⟩
def Program.Computes {k Q} (P : Program k Q) (s t : Store k) (bound : ℕ) : Prop :=
∃ n ≤ bound, (P.run s n).store = t ∧ P.step (P.run s n) = none
def symbol (b : Bool) : Fin 3 := bitSymbol b
def unsymbol (a : Fin 3) : Option Bool :=
if a = 0 then none else some (a = 2)
@[simp] theorem unsymbol_symbol (b : Bool) : unsymbol (symbol b) = some b := by
cases b <;> decide
@[simp] theorem unsymbol_zero : unsymbol 0 = none := rfl
def stackTape (xs : List Bool) : Turing.Tape (Fin 3) :=
Turing.Tape.mk₁ (xs.map symbol)
def phaseOne (a : Action) (head : Fin 3) : Fin 3 × Option Turing.Dir :=
match a with
| .stay => (head,none)
| .pop => (0,some .right)
| .push _ => (head,some .left)
def phaseTwo (a : Action) (head : Fin 3) : Fin 3 × Option Turing.Dir :=
match a with
| .push b => (symbol b,none)
| _ => (head,none)
def applyTape (a : Fin 3 × Option Turing.Dir) (t : Turing.Tape (Fin 3)) :
Turing.Tape (Fin 3) :=
match a.2 with
| none => t.write a.1
| some d => (t.write a.1).move d
def middleTape (a : Action) (xs : List Bool) : Turing.Tape (Fin 3) :=
applyTape (phaseOne a (stackTape xs).head) (stackTape xs)
@[simp] theorem blank_cons :
(Turing.ListBlank.mk ([] : List (Fin 3))).cons 0 = Turing.ListBlank.mk [] := by
exact Turing.ListBlank.cons_head_tail (Turing.ListBlank.mk [])
abbrev Control (k : ℕ) (Q : Type) := Q ⊕ (Q × Actions k)
section Compilation
variable {k : ℕ} {Q : Type} [Fintype Q] (P : Program k Q)
noncomputable def numberControl (q : Control k Q) : Fin (Fintype.card (Control k Q) + 1) :=
(Fintype.equivFin (Control k Q) q).succ
noncomputable def readControl (i : Fin (Fintype.card (Control k Q) + 1)) : Control k Q :=
if h : i.val = 0 then .inl P.initial else
(Fintype.equivFin (Control k Q)).symm ⟨i.val-1, by have := i.isLt; omega⟩
@[simp] theorem read_numberControl (q : Control k Q) : readControl P (numberControl q) = q := by
simp [readControl, numberControl]
@[simp] theorem read_zero : readControl P 0 = .inl P.initial := by
simp [readControl]
noncomputable def compile : Machine k (Fintype.card (Control k Q)) 0 where
transition i heads :=
match readControl P i with
| .inl q => (P.transition q (fun j => unsymbol (heads j))).map
(fun qa => (numberControl (.inr qa), fun j => phaseOne (qa.2 j) (heads j)))
| .inr qa => some (numberControl (.inl qa.1), fun j => phaseTwo (qa.2 j) (heads j))
abbrev TapeCfg := Configuration k (Fintype.card (Control k Q)) 0
def Relates (c : TapeCfg (k := k) (Q := Q)) (s : State k Q) : Prop :=
readControl P c.state = .inl s.control ∧ ∀ j, c.tapes j = stackTape (s.store j)
noncomputable def middleCfg (qa : Q × Actions k) (s : Store k) : TapeCfg (k := k) (Q := Q) :=
⟨numberControl (.inr qa), fun j => middleTape (qa.2 j) (s j)⟩
noncomputable def readyCfg (s : State k Q) : TapeCfg (k := k) (Q := Q) :=
⟨numberControl (.inl s.control), fun j => stackTape (s.store j)⟩
@[simp] theorem relates_ready (s : State k Q) : Relates P (readyCfg s) s :=
⟨read_numberControl P _, fun _ => rfl⟩
def initialStore (input : List Bool) : Store k := fun i => if i = 0 then input else []
end Compilation
namespace Program
variable {k : ℕ} {Q R S : Type}
inductive Exec (P : Program k Q) : State k Q → ℕ → State k Q → Prop
| halt {s} : P.step s = none → Exec P s 0 s
| next {s t u n} : P.step s = some t → Exec P t n u → Exec P s (n+1) u
def State.mapControl (f : Q → R) (s : State k Q) : State k R := ⟨f s.control,s.store⟩
def stayActions : Actions k := fun _ => .stay
def seq (P : Program k Q) (P' : Program k R) : Program k (Q ⊕ R) where
initial := .inl P.initial
transition q heads := match q with
| .inl q => match P.transition q heads with
| none => some (.inr P'.initial,stayActions)
| some qa => some (.inl qa.1,qa.2)
| .inr q => (P'.transition q heads).map (fun qa => (.inr qa.1,qa.2))
def instruction (a : Heads k → Actions k) : Program k Bool where
initial := false
transition q h := if q then none else some (true,a h)
def loop (test : Heads k → Bool) (P : Program k Q) : Program k (Option Q) where
initial := none
transition q h := match q with
| none => if test h then some (some P.initial,stayActions) else none
| some q => match P.transition q h with
| none => some (none,stayActions)
| some qa => some (some qa.1,qa.2)
end Program
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
namespace Program
variable {k : ℕ}
def transferActions (src dst : Fin (k+1)) (h : Heads k) : Actions k := fun i =>
if i = src then .pop else if i = dst then .push ((h src).getD false) else .stay
def transfer (src dst : Fin (k+1)) : Program k (Option Bool) :=
loop (fun h => (h src).isSome) (instruction (transferActions src dst))
def transferResult (src dst : Fin (k+1)) (s : Store k) : Store k :=
Function.update (Function.update s src []) dst ((s src).reverse ++ s dst)
def transferOnce (src dst : Fin (k+1)) (b : Bool) (xs : List Bool) (s : Store k) : Store k :=
Function.update (Function.update s src xs) dst (b :: s dst)
end Program
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Program
variable {k : ℕ}
def popActions (src : Fin (k+1)) : Actions k := fun i => if i = src then .pop else .stay
def clear (src : Fin (k+1)) : Program k (Option Bool) :=
loop (fun h => (h src).isSome) (instruction (fun _ => popActions src))
def spreadActions (src dst₁ dst₂ : Fin (k+1)) (h : Heads k) : Actions k := fun i =>
if i = src then .pop else if i = dst₁ ∨ i = dst₂ then .push ((h src).getD false) else .stay
def spread (src dst₁ dst₂ : Fin (k+1)) : Program k (Option Bool) :=
loop (fun h => (h src).isSome) (instruction (spreadActions src dst₁ dst₂))
def spreadResult (src dst₁ dst₂ : Fin (k+1)) (s : Store k) : Store k :=
Function.update (Function.update (Function.update s src [])
dst₁ ((s src).reverse ++ s dst₁)) dst₂ ((s src).reverse ++ s dst₂)
def spreadOnce (src dst₁ dst₂ : Fin (k+1)) (b : Bool) (xs : List Bool) (s : Store k) : Store k :=
Function.update (Function.update (Function.update s src xs) dst₁ (b :: s dst₁)) dst₂ (b :: s dst₂)
def prepend (src dst tmp : Fin (k+1)) : Program k (Option Bool ⊕ Option Bool) :=
seq (transfer src tmp) (spread tmp src dst)
end ThreeMachine.StackCompiler.Program
namespace ThreeMachine.StackCompiler.Program
variable {k : ℕ}
def copy (src dst tmp : Fin (k+1)) : Program k (Option Bool ⊕ (Option Bool ⊕ Option Bool)) :=
seq (clear dst) (prepend src dst tmp)
end ThreeMachine.StackCompiler.Program
end
end OAI
end
section
-- module TreeData
namespace OAI
section
namespace ThreeMachine.StackCompiler
inductive Data
| nil
| pair (head tail : Data)
deriving DecidableEq
namespace Data
def encode : Data → List Bool
| .nil => [false]
| .pair a b => true :: a.encode ++ b.encode
def size (d : Data) : ℕ := d.encode.length
@[simp] theorem encode_nil : encode nil = [false] := rfl
@[simp] theorem encode_pair (a b : Data) : encode (pair a b) = true :: a.encode ++ b.encode := rfl
@[simp] theorem size_nil : size nil = 1 := rfl
@[simp] theorem size_pair (a b : Data) : size (pair a b) = a.size + b.size + 1 := by
simp [size,encode,Nat.add_comm]
def head : Data → Data | .nil => .nil | .pair a _ => a
def tail : Data → Data | .nil => .nil | .pair _ b => b
end Data
namespace Program
variable {k : ℕ}
def scanActions (src dst ct : Fin (k+1)) (h : Heads k) : Actions k := fun i =>
if i = src then .pop else if i = dst then .push ((h src).getD false)
else if i = ct then if (h src).getD false then .push true else .pop else .stay
def scan (src dst ct : Fin (k+1)) : Program k (Option Bool) :=
loop (fun h => (h ct).isSome) (instruction (scanActions src dst ct))
def scanned (src dst ct : Fin (k+1)) (s : Store k) (rest word : List Bool) (c : ℕ) : Store k :=
Function.update (Function.update (Function.update s src rest) dst (word.reverse ++ s dst))
ct (List.replicate c true)
def scanOnce (src dst ct : Fin (k+1)) (s : Store k) (b : Bool) (rest : List Bool) : Store k :=
Function.update (Function.update (Function.update s src rest) dst (b :: s dst))
ct (if b then true :: s ct else (s ct).tail)
end Program
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Program
variable {k : ℕ} {Q R : Type}
def Runs (P : Program k Q) (s t : Store k) (bound : ℕ) : Prop :=
∃ n ≤ bound, ∃ q, Exec P ⟨P.initial,s⟩ n ⟨q,t⟩
def branch (test : Heads k → Bool) (P : Program k Q) (P' : Program k R) :
Program k (Option (Q ⊕ R)) where
initial := none
transition q h := match q with
| none => some (some (if test h then .inl P.initial else .inr P'.initial),stayActions)
| some (.inl q) => (P.transition q h).map (fun qa => (some (.inl qa.1),qa.2))
| some (.inr q) => (P'.transition q h).map (fun qa => (some (.inr qa.1),qa.2))
def move (src dst tmp : Fin (k+1)) : Program k (Option Bool ⊕ (Option Bool ⊕ Option Bool)) :=
seq (clear dst) (seq (transfer src tmp) (transfer tmp dst))
end ThreeMachine.StackCompiler.Program
namespace ThreeMachine.StackCompiler.Program
variable {k : ℕ}
def push (dst : Fin (k+1)) (b : Bool) : Program k Bool :=
instruction (fun _ i => if i = dst then .push b else .stay)
def setNil (dst : Fin (k+1)) := seq (clear dst) (push dst false)
def setPair (dst a b tmp buf : Fin (k+1)) :=
seq (prepend b tmp buf) (seq (prepend a tmp buf)
(seq (push tmp true) (move tmp dst buf)))
end ThreeMachine.StackCompiler.Program
end
end OAI
end
section
-- module RegisterMachine
namespace OAI
section
namespace ThreeMachine.StackCompiler
structure Packed (k : ℕ) where
Control : Type
finiteControl : Fintype Control
program : Program k Control
attribute [instance] Packed.finiteControl
namespace Packed
variable {k : ℕ}
def ofProgram {Q : Type} [Fintype Q] (p : Program k Q) : Packed k := ⟨Q,inferInstance,p⟩
def seq (P P' : Packed k) : Packed k := ofProgram (Program.seq P.program P'.program)
def branch (test : Heads k → Bool) (P P' : Packed k) : Packed k :=
ofProgram (Program.branch test P.program P'.program)
def loop (test : Heads k → Bool) (P : Packed k) : Packed k :=
ofProgram (Program.loop test P.program)
def Runs (P : Packed k) := P.program.Runs
end Packed
namespace Tree
variable {r : ℕ}
abbrev Registers (r : ℕ) := Fin r → Data
def reg (i : Fin r) : Fin (r+4) := i.castAdd 4
def temp (i : Fin 4) : Fin (r+4) := i.natAdd r
def memory (s : Registers r) : Store (r+3) :=
Fin.append (m := r) (n := 4) (fun i : Fin r => (s i).encode) (fun _ : Fin 4 => [])
@[simp] theorem memory_reg (s : Registers r) (i : Fin r) : memory s (reg i) = (s i).encode :=
Fin.append_left _ _ _
@[simp] theorem memory_temp (s : Registers r) (i : Fin 4) : memory s (temp i) = [] :=
Fin.append_right _ _ _
@[simp] theorem reg_ne_temp (i : Fin r) (j : Fin 4) : reg i ≠ temp j := by
intro he
have hv := congrArg Fin.val he
simp only [reg,temp,Fin.val_castAdd,Fin.val_natAdd] at hv
omega
@[simp] theorem temp_ne_reg (i : Fin r) (j : Fin 4) : temp j ≠ reg i := (reg_ne_temp i j).symm
@[simp] theorem reg_eq_reg (i j : Fin r) : reg i = reg j ↔ i = j := Fin.castAdd_inj
@[simp] theorem temp_eq_temp (i j : Fin 4) : (temp i : Fin (r+4)) = temp j ↔ i = j := Fin.natAdd_inj r
def nil (dst : Fin r) : Packed (r+3) := Packed.ofProgram (Program.setNil (reg dst))
def pair (dst a b : Fin r) : Packed (r+3) :=
Packed.ofProgram (Program.setPair (reg dst) (reg a) (reg b) (temp 0) (temp 1))
end Tree
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Tree
variable {r : ℕ}
def work (s : Registers r) (t : Fin 4 → List Bool) : Store (r+3) :=
Fin.append (m := r) (n := 4) (fun i : Fin r => (s i).encode) t
@[simp] theorem work_reg (s : Registers r) (t : Fin 4 → List Bool) (i : Fin r) :
work s t (reg i) = (s i).encode := Fin.append_left _ _ _
@[simp] theorem work_temp (s : Registers r) (t : Fin 4 → List Bool) (i : Fin 4) :
work s t (temp i) = t i := Fin.append_right _ _ _
@[simp] theorem work_empty (s : Registers r) : work s ![[],[],[],[]] = memory s := by
have he : (![[],[],[],[]] : Fin 4 → List Bool) = fun _ => [] := by
funext i; fin_cases i <;> rfl
simp only [work,memory,he]
def selectFinish (head : Bool) : Packed (r+3) :=
if head then Packed.ofProgram (Program.seq (Program.clear (temp 0)) (Program.transfer (temp 2) (temp 0)))
else Packed.ofProgram (Program.seq (Program.clear (temp 2)) (Program.clear (temp 2)))
def selectPair (head : Bool) (dst : Fin r) : Packed (r+3) :=
(Packed.ofProgram (Program.instruction (fun _ => Program.popActions (temp 0)))).seq
((Packed.ofProgram (Program.push (temp 3) true)).seq
((Packed.ofProgram (Program.scan (temp 0) (temp 2) (temp 3))).seq
((selectFinish head).seq (Packed.ofProgram (Program.move (temp 0) (reg dst) (temp 1))))))
def selectAux (head : Bool) (dst : Fin r) : Packed (r+3) :=
Packed.branch (fun h => (h (temp 0)).getD false) (selectPair head dst)
(Packed.ofProgram (Program.move (temp 0) (reg dst) (temp 1)))
def select (head : Bool) (dst src : Fin r) : Packed (r+3) :=
(Packed.ofProgram (Program.copy (reg src) (temp 0) (temp 1))).seq (selectAux head dst)
end ThreeMachine.StackCompiler.Tree
namespace ThreeMachine.StackCompiler.Tree
variable {r : ℕ}
end ThreeMachine.StackCompiler.Tree
namespace ThreeMachine.StackCompiler.Program
variable {k : ℕ} {Q : Type}
end ThreeMachine.StackCompiler.Program
namespace ThreeMachine.StackCompiler.Tree
variable {r : ℕ}
def skip : Packed (r+3) := Packed.ofProgram (Program.instruction (fun _ => Program.stayActions))
def copy (dst src : Fin r) : Packed (r+3) :=
if dst = src then skip else Packed.ofProgram (Program.copy (reg src) (reg dst) (temp 0))
inductive Code (V : Type)
| skip
| nil (dst : V)
| pair (dst a b : V)
| select (head : Bool) (dst src : V)
| copy (dst src : V)
| seq (first second : Code V)
| branch (src : V) (nonempty empty : Code V)
| loop (src : V) (body : Code V)
def _root_.OAI.ThreeMachine.StackCompiler.Data.nonempty : Data → Bool | .nil => false | .pair _ _ => true
@[simp] theorem _root_.OAI.ThreeMachine.StackCompiler.Data.encode_head (d : Data) : d.encode.head?.getD false = d.nonempty := by
cases d <;> rfl
inductive Eval {V : Type} [DecidableEq V] : Code V → (V → Data) → (V → Data) → ℕ → Prop
| skip (s) : Eval .skip s s 1
| nil (dst) (s) : Eval (.nil dst) s (Function.update s dst .nil) (1+(s dst).size)
| pair (dst a b) (s) : Eval (.pair dst a b) s (Function.update s dst (.pair (s a) (s b))) (1+(s dst).size+(s a).size+(s b).size)
| select (head dst src) (s) :
Eval (.select head dst src) s (Function.update s dst (if head then (s src).head else (s src).tail)) (1+(s dst).size+(s src).size)
| copy (dst src) (s) : Eval (.copy dst src) s (Function.update s dst (s src)) (1+(s dst).size+(s src).size)
| seq {p q s t u n m} : Eval p s t n → Eval q t u m → Eval (.seq p q) s u (n+m+1)
| branch_true {src p q s t n} : (s src).nonempty = true → Eval p s t n → Eval (.branch src p q) s t (n+1)
| branch_false {src p q s t n} : (s src).nonempty = false → Eval q s t n → Eval (.branch src p q) s t (n+1)
| loop_stop {src p s} : (s src).nonempty = false → Eval (.loop src p) s s 1
| loop_step {src p s t u n m} : (s src).nonempty = true → Eval p s t n →
Eval (.loop src p) t u m → Eval (.loop src p) s u (n+m+1)
namespace Code
def compile : Code (Fin r) → Packed (r+3)
| .skip => Tree.skip
| .nil dst => Tree.nil dst
| .pair dst a b => Tree.pair dst a b
| .select head dst src => Tree.select head dst src
| .copy dst src => Tree.copy dst src
| .seq p q => p.compile.seq q.compile
| .branch src p q => Packed.branch (fun h => (h (reg src)).getD false) p.compile q.compile
| .loop src p => Packed.loop (fun h => (h (reg src)).getD false) p.compile
end Code
end ThreeMachine.StackCompiler.Tree
end
end OAI
end
section
-- module RoutineCompiler
namespace OAI
section
namespace ThreeMachine.StackCompiler.Tree
variable {V W : Type} [DecidableEq V] [DecidableEq W]
def Code.rename (f : V → W) : Code V → Code W
| .skip => .skip
| .nil dst => .nil (f dst)
| .pair dst a b => .pair (f dst) (f a) (f b)
| .select head dst src => .select head (f dst) (f src)
| .copy dst src => .copy (f dst) (f src)
| .seq p q => .seq (p.rename f) (q.rename f)
| .branch src p q => .branch (f src) (p.rename f) (q.rename f)
| .loop src p => .loop (f src) (p.rename f)
noncomputable def overlay (f : V → W) (s : V → Data) (base : W → Data) : W → Data :=
Function.extend f s base
omit [DecidableEq V] [DecidableEq W] in
theorem overlay_apply {f : V → W} (hf : Function.Injective f) (s : V → Data) (base : W → Data) (i : V) :
overlay f s base (f i) = s i := hf.extend_apply s base i
omit [DecidableEq V] [DecidableEq W] in
theorem overlay_out {f : V → W} (s : V → Data) (base : W → Data) {j : W} (hj : ¬∃ i, f i = j) :
overlay f s base j = base j := Function.extend_apply' s base j hj
theorem overlay_update {f : V → W} (hf : Function.Injective f) (s : V → Data) (base : W → Data)
(i : V) (d : Data) :
overlay f (Function.update s i d) base = Function.update (overlay f s base) (f i) d := by
funext j
by_cases hj : ∃ a, f a = j
· obtain ⟨a,rfl⟩ := hj
by_cases ha : a = i <;> simp [overlay_apply hf,ha,hf.eq_iff]
· have hn : j ≠ f i := fun h => hj ⟨i,h.symm⟩
rw [overlay_out _ _ hj,Function.update_of_ne hn,overlay_out _ _ hj]
theorem Eval.rename {p : Code V} {s t : V → Data} {n : ℕ} (h : Eval p s t n)
{f : V → W} (hf : Function.Injective f) (base : W → Data) :
Eval (p.rename f) (overlay f s base) (overlay f t base) n := by
induction h with
| skip s => exact Eval.skip _
| nil dst s => simpa only [Code.rename,overlay_update hf,overlay_apply hf] using Eval.nil (f dst) (overlay f s base)
| pair dst a b s => simpa only [Code.rename,overlay_update hf,overlay_apply hf] using Eval.pair (f dst) (f a) (f b) (overlay f s base)
| select head dst src s => simpa only [Code.rename,overlay_update hf,overlay_apply hf] using Eval.select head (f dst) (f src) (overlay f s base)
| copy dst src s => simpa only [Code.rename,overlay_update hf,overlay_apply hf] using Eval.copy (f dst) (f src) (overlay f s base)
| seq _ _ ih ih' => exact Eval.seq ih ih'
| branch_true hs _ ih => exact Eval.branch_true (by simpa only [overlay_apply hf] using hs) ih
| branch_false hs _ ih => exact Eval.branch_false (by simpa only [overlay_apply hf] using hs) ih
| loop_stop hs => exact Eval.loop_stop (by simpa only [overlay_apply hf] using hs)
| loop_step hs _ _ ih ih' => exact Eval.loop_step (by simpa only [overlay_apply hf] using hs) ih ih'
end ThreeMachine.StackCompiler.Tree
namespace ThreeMachine.StackCompiler.Tree
variable {V W : Type} [DecidableEq V] [DecidableEq W]
def Bounded (p : Code V) (s t : V → Data) (bound : ℕ) : Prop :=
∃ n ≤ bound, Eval p s t n
theorem Eval.bounded {p : Code V} {s t : V → Data} {n : ℕ} (h : Eval p s t n) : Bounded p s t n :=
⟨n,le_rfl,h⟩
theorem Bounded.mono {p : Code V} {s t : V → Data} {n m : ℕ} (h : Bounded p s t n) (h' : n ≤ m) :
Bounded p s t m := by
obtain ⟨a,ha,he⟩ := h
exact ⟨a,ha.trans h',he⟩
theorem Bounded.seq {p q : Code V} {s t u : V → Data} {n m : ℕ}
(h : Bounded p s t n) (h' : Bounded q t u m) : Bounded (.seq p q) s u (n+m+1) := by
obtain ⟨a,ha,he⟩ := h
obtain ⟨b,hb,he'⟩ := h'
exact ⟨a+b+1,by omega,Eval.seq he he'⟩
def join (s : V → Data) (t : W → Data) : V ⊕ W → Data := Sum.elim s t
omit [DecidableEq V] [DecidableEq W] in
@[simp] theorem join_inl (s : V → Data) (t : W → Data) (i : V) : join s t (.inl i) = s i := rfl
omit [DecidableEq V] [DecidableEq W] in
@[simp] theorem join_inr (s : V → Data) (t : W → Data) (i : W) : join s t (.inr i) = t i := rfl
theorem join_update_left (s : V → Data) (t : W → Data) (i : V) (d : Data) :
Function.update (join s t) (.inl i) d = join (Function.update s i d) t := by
funext j
cases j with
| inl j => by_cases hj : j = i <;> simp [hj]
| inr j => simp
theorem join_update_right (s : V → Data) (t : W → Data) (i : W) (d : Data) :
Function.update (join s t) (.inr i) d = join s (Function.update t i d) := by
funext j
cases j with
| inl j => simp
| inr j => by_cases hj : j = i <;> simp [hj]
omit [DecidableEq V] [DecidableEq W] in
theorem overlay_left (s s' : V → Data) (t : W → Data) : overlay Sum.inl s (join s' t) = join s t := by
funext j
cases j with
| inl j => exact overlay_apply Sum.inl_injective _ _ _
| inr j => exact overlay_out _ _ (by simp)
omit [DecidableEq V] [DecidableEq W] in
theorem overlay_right (s : V → Data) (t t' : W → Data) : overlay Sum.inr t (join s t') = join s t := by
funext j
cases j with
| inl j => exact overlay_out _ _ (by simp)
| inr j => exact overlay_apply Sum.inr_injective _ _ _
theorem Bounded.left {p : Code V} {s t : V → Data} {n : ℕ}
(h : Bounded p s t n) (u : W → Data) : Bounded (p.rename Sum.inl) (join s u) (join t u) n := by
obtain ⟨m,hm,he⟩ := h
refine ⟨m,hm,?_⟩
simpa only [overlay_left] using he.rename Sum.inl_injective (join s u)
theorem Bounded.right {p : Code W} {s t : W → Data} {n : ℕ}
(h : Bounded p s t n) (u : V → Data) : Bounded (p.rename Sum.inr) (join u s) (join u t) n := by
obtain ⟨m,hm,he⟩ := h
refine ⟨m,hm,?_⟩
simpa only [overlay_right] using he.rename Sum.inr_injective (join u s)
end ThreeMachine.StackCompiler.Tree
namespace ThreeMachine.StackCompiler
open ThreeMachine.StackCompiler.Tree
def zeroStore (V : Type) : V → Data := fun _ => .nil
def start {V : Type} [DecidableEq V] (input : V) (x : Data) : V → Data :=
Function.update (zeroStore V) input x
def finish {V : Type} [DecidableEq V] (input output : V) (x y : Data) : V → Data :=
Function.update (start input x) output y
structure Routine (f : Data → Data) (charge : Data → ℕ) where
Vars : Type
finiteVars : Fintype Vars
decVars : DecidableEq Vars
input : Vars
output : Vars
distinct : input ≠ output
code : Code Vars
correct : ∀ x, Bounded code (start input x) (finish input output x (f x)) (charge x)
attribute [instance] Routine.finiteVars Routine.decVars
namespace Routine
variable {f g : Data → Data} {charge charge' : Data → ℕ}
def mono (R : Routine f charge) (h : ∀ x, charge x ≤ charge' x) : Routine f charge' :=
{ R with correct := fun x => (R.correct x).mono (h x) }
def identity : Routine id (fun x => x.size+2) where
Vars := Bool
finiteVars := inferInstance
decVars := inferInstance
input := false
output := true
distinct := by decide
code := .copy true false
correct x := by
simpa [finish,start,zeroStore,Nat.add_comm] using (Eval.copy true false (start false x)).bounded
def nil : Routine (fun _ => Data.nil) (fun _ => 2) where
Vars := Bool
finiteVars := inferInstance
decVars := inferInstance
input := false
output := true
distinct := by decide
code := .nil true
correct x := by
simpa [finish,start,zeroStore] using (Eval.nil true (start false x)).bounded
def select (head : Bool) : Routine (fun x => if head then x.head else x.tail) (fun x => x.size+2) where
Vars := Bool
finiteVars := inferInstance
decVars := inferInstance
input := false
output := true
distinct := by decide
code := .select head true false
correct x := by
simpa [finish,start,zeroStore,Nat.add_comm] using (Eval.select head true false (start false x)).bounded
end Routine
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
open ThreeMachine.StackCompiler.Tree
variable {V W : Type} [DecidableEq V] [DecidableEq W]
@[simp] theorem start_input (input : V) (x : Data) : start input x input = x := by simp [start]
@[simp] theorem start_other {input i : V} (x : Data) (hi : i ≠ input) : start input x i = .nil := by simp [start,hi,zeroStore]
@[simp] theorem finish_output (input output : V) (x y : Data) : finish input output x y output = y := by simp [finish]
@[simp] theorem finish_input {input output : V} (h : input ≠ output) (x y : Data) : finish input output x y input = x := by simp [finish,start,h]
theorem start_left (input : V) (x : Data) :
start (Sum.inl input : V ⊕ W) x = join (start input x) (zeroStore W) := by
funext j
cases j with
| inl j => by_cases hj : j = input <;> simp [hj,start,zeroStore]
| inr j => simp [start,zeroStore]
theorem finish_lr (input : V) (output : W) (x y : Data) :
finish (Sum.inl input) (Sum.inr output) x y = join (start input x) (start output y) := by
rw [finish,start_left,join_update_right]
rfl
theorem reset_output {input output : V} (h : input ≠ output) (x y : Data) :
Function.update (finish input output x y) output .nil = start input x := by
have he : start input x output = .nil := start_other x h.symm
rw [finish,Function.update_idem,← he,Function.update_eq_self]
theorem reset_input {input output : V} (h : input ≠ output) (x y : Data) :
Function.update (finish input output x y) input .nil = start output y := by
funext i
by_cases hi : i = input
· subst i; simp [start,h,zeroStore]
· by_cases ho : i = output
· subst i; simp [hi,start]
· simp [finish,start,hi,ho,zeroStore]
namespace Routine
variable {f g : Data → Data} {c d : Data → ℕ}
def compCode (R : Routine f c) (S : Routine g d) : Code (R.Vars ⊕ S.Vars) :=
.seq (R.code.rename Sum.inl)
(.seq (.copy (.inr S.input) (.inl R.output))
(.seq (S.code.rename Sum.inr)
(.seq (.nil (.inl R.output)) (.nil (.inr S.input)))))
def comp (R : Routine f c) (S : Routine g d) :
Routine (g ∘ f) (fun x => c x+d (f x)+10*((f x).size+1)) where
Vars := R.Vars ⊕ S.Vars
finiteVars := inferInstance
decVars := inferInstance
input := .inl R.input
output := .inr S.output
distinct := by simp
code := compCode R S
correct x := by
let a := start R.input x
let a' := finish R.input R.output x (f x)
let b := start S.input (f x)
let b' := finish S.input S.output (f x) (g (f x))
have h₁ : Bounded (R.code.rename Sum.inl) (join a (zeroStore S.Vars)) (join a' (zeroStore S.Vars)) (c x) :=
(R.correct x).left _
have h₂ : Bounded (.copy (.inr S.input) (.inl R.output))
(join a' (zeroStore S.Vars)) (join a' b) ((f x).size+2) := by
simpa [join_update_right,a',b,zeroStore,start,Nat.add_comm] using
(Eval.copy (.inr S.input) (.inl R.output) (join a' (zeroStore S.Vars))).bounded
have h₃ : Bounded (S.code.rename Sum.inr) (join a' b) (join a' b') (d (f x)) :=
(S.correct (f x)).right _
have h₄ : Bounded (.nil (.inl R.output)) (join a' b') (join a b') (1+(f x).size) := by
simpa only [join_update_left,a',a,reset_output R.distinct,join_inl,finish_output] using
(Eval.nil (.inl R.output) (join a' b')).bounded
have h₅ : Bounded (.nil (.inr S.input)) (join a b') (join a (start S.output (g (f x)))) (1+(f x).size) := by
simpa only [join_update_right,b',reset_input S.distinct,join_inr,finish_input S.distinct] using
(Eval.nil (.inr S.input) (join a b')).bounded
have hh := h₁.seq (h₂.seq (h₃.seq (h₄.seq h₅)))
simpa only [start_left,finish_lr,Function.comp_apply] using
(show Bounded (compCode R S) (join a (zeroStore S.Vars)) (join a (start S.output (g (f x))))
(c x+d (f x)+10*((f x).size+1)) from hh.mono (by omega))
end Routine
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
open ThreeMachine.StackCompiler.Tree
variable {V : Type} [DecidableEq V]
theorem reset_start (input : V) (x : Data) :
Function.update (start input x) input .nil = zeroStore V := by
funext i
by_cases h : i = input <;> simp [start,zeroStore,h]
namespace Routine
variable {f g : Data → Data} {c d : Data → ℕ}
def pairCode (R : Routine f c) (S : Routine g d) : Code ((R.Vars ⊕ S.Vars) ⊕ Unit) :=
.seq ((R.code.rename Sum.inl).rename Sum.inl)
(.seq (.copy (.inl (.inr S.input)) (.inl (.inl R.input)))
(.seq ((S.code.rename Sum.inr).rename Sum.inl)
(.seq (.pair (.inr ()) (.inl (.inl R.output)) (.inl (.inr S.output)))
(.seq (.nil (.inl (.inl R.output)))
(.seq (.nil (.inl (.inr S.output))) (.nil (.inl (.inr S.input))))))))
def pair (R : Routine f c) (S : Routine g d) :
Routine (fun x => Data.pair (f x) (g x))
(fun x => c x+d x+20*(x.size+(f x).size+(g x).size+1)) where
Vars := (R.Vars ⊕ S.Vars) ⊕ Unit
finiteVars := inferInstance
decVars := inferInstance
input := .inl (.inl R.input)
output := .inr ()
distinct := by simp
code := pairCode R S
correct x := by
let a := start R.input x
let a' := finish R.input R.output x (f x)
let b := start S.input x
let b' := finish S.input S.output x (g x)
let z := zeroStore Unit
let o := start () (Data.pair (f x) (g x))
have h₁ := ((R.correct x).left (zeroStore S.Vars)).left z
have h₂ : Bounded (.copy (.inl (.inr S.input)) (.inl (.inl R.input)))
(join (join a' (zeroStore S.Vars)) z) (join (join a' b) z) (x.size+2) := by
simpa [join_update_left,join_update_right,a',b,zeroStore,start,R.distinct,Nat.add_comm] using
(Eval.copy (.inl (.inr S.input)) (.inl (.inl R.input))
(join (join a' (zeroStore S.Vars)) z)).bounded
have h₃ := ((S.correct x).right a').left z
have h₄ : Bounded (.pair (.inr ()) (.inl (.inl R.output)) (.inl (.inr S.output)))
(join (join a' b') z) (join (join a' b') o) (2+(f x).size+(g x).size) := by
simpa [join_update_right,o,z,zeroStore,start,a',b'] using
(Eval.pair (.inr ()) (.inl (.inl R.output)) (.inl (.inr S.output))
(join (join a' b') z)).bounded
have h₅ : Bounded (.nil (.inl (.inl R.output)))
(join (join a' b') o) (join (join a b') o) (1+(f x).size) := by
simpa only [join_update_left,a',a,reset_output R.distinct,join_inl,finish_output] using
(Eval.nil (.inl (.inl R.output)) (join (join a' b') o)).bounded
have h₆ : Bounded (.nil (.inl (.inr S.output)))
(join (join a b') o) (join (join a b) o) (1+(g x).size) := by
simpa only [join_update_left,join_update_right,b',b,reset_output S.distinct,join_inr,join_inl,finish_output] using
(Eval.nil (.inl (.inr S.output)) (join (join a b') o)).bounded
have h₇ : Bounded (.nil (.inl (.inr S.input)))
(join (join a b) o) (join (join a (zeroStore S.Vars)) o) (1+x.size) := by
simpa only [join_update_left,join_update_right,b,reset_start,join_inr,join_inl,start_input] using
(Eval.nil (.inl (.inr S.input)) (join (join a b) o)).bounded
have hh := h₁.seq (h₂.seq (h₃.seq (h₄.seq (h₅.seq (h₆.seq h₇)))))
simpa only [start_left,finish_lr] using
(show Bounded (pairCode R S) (join (join a (zeroStore S.Vars)) z)
(join (join a (zeroStore S.Vars)) o)
(c x+d x+20*(x.size+(f x).size+(g x).size+1)) from hh.mono (by omega))
end Routine
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Tree
variable {V : Type} [DecidableEq V]
theorem Bounded.loop_stop (src : V) (p : Code V) (s : V → Data)
(h : (s src).nonempty = false) : Bounded (.loop src p) s s 1 :=
(Eval.loop_stop h).bounded
theorem Bounded.loop_step {src : V} {p : Code V} {s t u : V → Data} {n m : ℕ}
(h : (s src).nonempty = true) (hp : Bounded p s t n)
(hq : Bounded (.loop src p) t u m) : Bounded (.loop src p) s u (n+m+1) := by
obtain ⟨n',hn,he⟩ := hp
obtain ⟨m',hm,he'⟩ := hq
exact ⟨n'+m'+1,by omega,Eval.loop_step h he he'⟩
end ThreeMachine.StackCompiler.Tree
end
end OAI
end
section
-- module Realizers
namespace OAI
universe u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16 u17 u18 u19 u20 u21 u22 u23 u24 u25 u26 u27
section
namespace ThreeMachine.StackCompiler
open ThreeMachine.StackCompiler.Tree
namespace Data
def fold (f : Data → Data) (acc : Data) : Data → Data
| .nil => acc
| .pair a xs => fold f (f (.pair a acc)) xs
def foldCost (f : Data → Data) (c : Data → ℕ) (acc : Data) : Data → ℕ
| .nil => 1
| .pair a xs => c (.pair a acc) + foldCost f c (f (.pair a acc)) xs +
20*((Data.pair a xs).size+acc.size+(f (.pair a acc)).size+1)
end Data
namespace Routine
variable {f : Data → Data} {c : Data → ℕ}
def foldStore (x acc xs : Data) : Fin 3 → Data := ![x,acc,xs]
@[simp] theorem foldStore_zero (x acc xs : Data) : foldStore x acc xs 0 = x := rfl
@[simp] theorem foldStore_one (x acc xs : Data) : foldStore x acc xs 1 = acc := rfl
@[simp] theorem foldStore_two (x acc xs : Data) : foldStore x acc xs 2 = xs := rfl
theorem foldStore_update_one (x acc xs y : Data) :
Function.update (foldStore x acc xs) 1 y = foldStore x y xs := by
funext i; fin_cases i <;> simp [foldStore]
theorem foldStore_update_two (x acc xs y : Data) :
Function.update (foldStore x acc xs) 2 y = foldStore x acc y := by
funext i; fin_cases i <;> simp [foldStore]
def foldBody (R : Routine f c) : Code (Fin 3 ⊕ R.Vars) :=
.seq (.select true (.inr R.input) (.inl 2))
(.seq (.pair (.inr R.input) (.inr R.input) (.inl 1))
(.seq (R.code.rename Sum.inr)
(.seq (.copy (.inl 1) (.inr R.output))
(.seq (.nil (.inr R.input))
(.seq (.nil (.inr R.output)) (.select false (.inl 2) (.inl 2)))))))
def foldCode (R : Routine f c) : Code (Fin 3 ⊕ R.Vars) :=
.seq (.select true (.inl 2) (.inl 0))
(.seq (.select false (.inl 1) (.inl 0)) (.loop (.inl 2) (foldBody R)))
theorem foldBody_correct (R : Routine f c) (x acc a xs : Data) :
Bounded (foldBody R)
(join (foldStore x acc (.pair a xs)) (zeroStore R.Vars))
(join (foldStore x (f (.pair a acc)) xs) (zeroStore R.Vars))
(c (.pair a acc)+20*((Data.pair a xs).size+acc.size+(f (.pair a acc)).size+1)-1) := by
let l := foldStore x acc (.pair a xs)
let l' := foldStore x (f (.pair a acc)) (.pair a xs)
let z := zeroStore R.Vars
let r := start R.input (.pair a acc)
let r' := finish R.input R.output (.pair a acc) (f (.pair a acc))
have h₁ : Bounded (.select true (.inr R.input) (.inl 2))
(join l z) (join l (start R.input a)) (2+(Data.pair a xs).size) := by
simpa [join_update_right,l,z,start,zeroStore,Data.head] using
(Eval.select true (.inr R.input) (.inl 2) (join l z)).bounded
have h₂ : Bounded (.pair (.inr R.input) (.inr R.input) (.inl 1))
(join l (start R.input a)) (join l r) (1+a.size+a.size+acc.size) := by
simpa [join_update_right,l,r,start,Function.update_idem] using
(Eval.pair (.inr R.input) (.inr R.input) (.inl 1) (join l (start R.input a))).bounded
have h₃ : Bounded (R.code.rename Sum.inr) (join l r) (join l r') (c (.pair a acc)) :=
(R.correct (.pair a acc)).right l
have h₄ : Bounded (.copy (.inl 1) (.inr R.output)) (join l r') (join l' r')
(1+acc.size+(f (.pair a acc)).size) := by
simpa [join_update_left,l,l',r',foldStore_update_one] using
(Eval.copy (.inl 1) (.inr R.output) (join l r')).bounded
have h₅ : Bounded (.nil (.inr R.input)) (join l' r')
(join l' (start R.output (f (.pair a acc)))) (1+(Data.pair a acc).size) := by
simpa only [join_update_right,r',reset_input R.distinct,join_inr,finish_input R.distinct] using
(Eval.nil (.inr R.input) (join l' r')).bounded
have h₆ : Bounded (.nil (.inr R.output))
(join l' (start R.output (f (.pair a acc)))) (join l' z) (1+(f (.pair a acc)).size) := by
simpa only [join_update_right,reset_start,join_inr,start_input,z] using
(Eval.nil (.inr R.output) (join l' (start R.output (f (.pair a acc))))).bounded
have h₇ : Bounded (.select false (.inl 2) (.inl 2)) (join l' z)
(join (foldStore x (f (.pair a acc)) xs) z) (1+(Data.pair a xs).size+(Data.pair a xs).size) := by
simpa [join_update_left,l',foldStore_update_two,Data.tail] using
(Eval.select false (.inl 2) (.inl 2) (join l' z)).bounded
have hh := h₁.seq (h₂.seq (h₃.seq (h₄.seq (h₅.seq (h₆.seq h₇)))))
exact hh.mono (by simp only [Data.size_pair]; omega)
theorem foldLoop_correct (R : Routine f c) (x acc xs : Data) :
Bounded (.loop (.inl 2) (foldBody R))
(join (foldStore x acc xs) (zeroStore R.Vars))
(join (foldStore x (Data.fold f acc xs) .nil) (zeroStore R.Vars))
(Data.foldCost f c acc xs) := by
induction xs generalizing acc with
| nil => exact Bounded.loop_stop _ _ _ rfl
| pair a xs _ ih =>
have hh := Bounded.loop_step (by rfl :
((join (foldStore x acc (.pair a xs)) (zeroStore R.Vars)) (.inl 2)).nonempty = true)
(foldBody_correct R x acc a xs) (ih (f (.pair a acc)))
exact hh.mono (by simp only [Data.foldCost]; omega)
def fold (R : Routine f c) :
Routine (fun x => Data.fold f x.tail x.head)
(fun x => 2*x.size+6+Data.foldCost f c x.tail x.head) where
Vars := Fin 3 ⊕ R.Vars
finiteVars := inferInstance
decVars := inferInstance
input := .inl 0
output := .inl 1
distinct := by simp
code := foldCode R
correct x := by
have es : start (0 : Fin 3) x = foldStore x .nil .nil := by
funext i; fin_cases i <;> simp [start,zeroStore,foldStore]
have ef : finish (Sum.inl (0 : Fin 3)) (Sum.inl (1 : Fin 3)) x (Data.fold f x.tail x.head) =
join (foldStore x (Data.fold f x.tail x.head) .nil) (zeroStore R.Vars) := by
rw [finish,start_left,es,join_update_left,foldStore_update_one]
have h₁ : Bounded (.select true (.inl 2) (.inl 0))
(join (foldStore x .nil .nil) (zeroStore R.Vars))
(join (foldStore x .nil x.head) (zeroStore R.Vars)) (2+x.size) := by
simpa [join_update_left,foldStore_update_two] using
(Eval.select true (.inl 2) (.inl 0)
(join (foldStore x .nil .nil) (zeroStore R.Vars))).bounded
have h₂ : Bounded (.select false (.inl 1) (.inl 0))
(join (foldStore x .nil x.head) (zeroStore R.Vars))
(join (foldStore x x.tail x.head) (zeroStore R.Vars)) (2+x.size) := by
simpa [join_update_left,foldStore_update_one] using
(Eval.select false (.inl 1) (.inl 0)
(join (foldStore x .nil x.head) (zeroStore R.Vars))).bounded
have hh := h₁.seq (h₂.seq (foldLoop_correct R x x.tail x.head))
rw [start_left,es,ef]
exact hh.mono (by omega)
end Routine
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
class Coding (α : Type u1) where
encode : α → Data
def enc {α : Type u2} [Coding α] : α → Data := Coding.encode
def volume {α : Type u3} [Coding α] (x : α) : ℕ := (enc x).size
instance : Coding Data := ⟨id⟩
instance : Coding Unit := ⟨fun _ => .nil⟩
instance : Coding Bool := ⟨fun b => if b then .pair .nil .nil else .nil⟩
instance {α : Type u4} {β : Type u5} [Coding α] [Coding β] : Coding (α × β) :=
⟨fun x => .pair (enc x.1) (enc x.2)⟩
def encodeList {α : Type u6} [Coding α] : List α → Data
| [] => .nil
| x :: xs => .pair (enc x) (encodeList xs)
instance {α : Type u7} [Coding α] : Coding (List α) := ⟨encodeList⟩
def encodeUnary : ℕ → Data | 0 => .nil | n+1 => .pair .nil (encodeUnary n)
instance : Coding ℕ := ⟨encodeUnary⟩
instance {α : Type u8} [Coding α] : Coding (Option α) :=
⟨fun x => match x with | none => .nil | some a => .pair (enc a) .nil⟩
@[simp] theorem enc_data (x : Data) : enc x = x := rfl
@[simp] theorem enc_unit (x : Unit) : enc x = .nil := rfl
@[simp] theorem enc_false : enc false = .nil := rfl
@[simp] theorem enc_true : enc true = .pair .nil .nil := rfl
@[simp] theorem enc_pair {α : Type u9} {β : Type u10} [Coding α] [Coding β] (x : α) (y : β) :
enc (x,y) = .pair (enc x) (enc y) := rfl
@[simp] theorem enc_nil {α : Type u11} [Coding α] : enc ([] : List α) = .nil := rfl
@[simp] theorem enc_cons {α : Type u12} [Coding α] (x : α) (xs : List α) :
enc (x :: xs) = .pair (enc x) (enc xs) := rfl
@[simp] theorem enc_zero : enc (0 : ℕ) = .nil := rfl
@[simp] theorem enc_succ (n : ℕ) : enc (n+1) = .pair .nil (enc n) := rfl
@[simp] theorem enc_none {α : Type u13} [Coding α] : enc (none : Option α) = .nil := rfl
@[simp] theorem enc_some {α : Type u14} [Coding α] (x : α) : enc (some x) = .pair (enc x) .nil := rfl
@[simp] theorem volume_pair {α : Type u15} {β : Type u16} [Coding α] [Coding β] (x : α) (y : β) :
volume (x,y) = volume x+volume y+1 := Data.size_pair _ _
@[simp] theorem volume_nil {α : Type u17} [Coding α] : volume ([] : List α) = 1 := rfl
@[simp] theorem volume_cons {α : Type u18} [Coding α] (x : α) (xs : List α) :
volume (x :: xs) = volume x+volume xs+1 := Data.size_pair _ _
@[simp] theorem volume_nat (n : ℕ) : volume n = 2*n+1 := by
induction n with
| zero => rfl
| succ n ih =>
change Data.size (.pair .nil (enc n)) = _
change (enc n).size = 2*n+1 at ih
simp only [Data.size_pair,Data.size_nil,ih]
omega
structure Realizer {α : Type u19} {β : Type u20} [Coding α] [Coding β] (f : α → β) where
transform : Data → Data
charge : Data → ℕ
routine : Routine transform charge
correct : ∀ x, transform (enc x) = enc (f x)
namespace Realizer
variable {α : Type u21} {β : Type u22} {γ : Type u23} {δ : Type u24} [Coding α] [Coding β] [Coding γ] [Coding δ]
variable {f : α → β} {g : β → γ}
def time (R : Realizer f) (x : α) : ℕ := R.charge (enc x)
def id : Realizer (_root_.id : α → α) :=
⟨_root_.id,_,Routine.identity,fun _ => rfl⟩
@[simp] theorem time_id (x : α) : (id : Realizer (_root_.id : α → α)).time x = volume x+2 := rfl
def unit : Realizer (fun _ : α => ()) :=
⟨fun _ => .nil,_,Routine.nil,fun _ => rfl⟩
def nil : Realizer (fun _ : α => ([] : List β)) :=
⟨fun _ => .nil,_,Routine.nil,fun _ => rfl⟩
def zero : Realizer (fun _ : α => (0 : ℕ)) :=
⟨fun _ => .nil,_,Routine.nil,fun _ => rfl⟩
def false : Realizer (fun _ : α => Bool.false) :=
⟨fun _ => .nil,_,Routine.nil,fun _ => rfl⟩
def comp (R : Realizer f) (S : Realizer g) : Realizer (g ∘ f) where
transform := S.transform ∘ R.transform
charge := _
routine := R.routine.comp S.routine
correct x := by simp only [Function.comp_apply,R.correct,S.correct]
theorem time_comp (R : Realizer f) (S : Realizer g) (x : α) :
(R.comp S).time x = R.time x+S.time (f x)+10*(volume (f x)+1) := by
simp only [comp,time,Routine.comp,R.correct,volume]
def pair {g : α → γ} (R : Realizer f) (S : Realizer g) : Realizer (fun x => (f x,g x)) where
transform := fun x => .pair (R.transform x) (S.transform x)
charge := _
routine := R.routine.pair S.routine
correct x := by simp only [R.correct,S.correct,enc_pair]
theorem time_pair {g : α → γ} (R : Realizer f) (S : Realizer g) (x : α) :
(R.pair S).time x = R.time x+S.time x+20*(volume x+volume (f x)+volume (g x)+1) := by
simp only [pair,time,Routine.pair,R.correct,S.correct,volume]
def fst : Realizer (Prod.fst : α × β → α) :=
⟨Data.head,_,Routine.select true,fun _ => rfl⟩
def snd : Realizer (Prod.snd : α × β → β) :=
⟨Data.tail,_,Routine.select Bool.false,fun _ => rfl⟩
@[simp] theorem time_fst (x : α × β) : (fst : Realizer (Prod.fst : α × β → α)).time x = volume x+2 := rfl
@[simp] theorem time_snd (x : α × β) : (snd : Realizer (Prod.snd : α × β → β)).time x = volume x+2 := rfl
def congr {f' : α → β} (R : Realizer f) (h : ∀ x, f x = f' x) : Realizer f' :=
{ R with correct := fun x => (R.correct x).trans (congrArg enc (h x)) }
@[simp] theorem time_congr {f' : α → β} (R : Realizer f) (h : ∀ x, f x = f' x) (x : α) :
(R.congr h).time x = R.time x := rfl
theorem fold_correct {F : α × β → β} (R : Realizer F) (xs : List α) (b : β) :
Data.fold R.transform (enc b) (enc xs) = enc (xs.foldl (fun b a => F (a,b)) b) := by
induction xs generalizing b with
| nil => rfl
| cons a xs ih =>
change Data.fold R.transform (R.transform (enc (a,b))) (enc xs) = _
rw [R.correct,ih]
rfl
def fold {F : α × β → β} (R : Realizer F) :
Realizer (fun x : List α × β => x.1.foldl (fun b a => F (a,b)) x.2) where
transform := fun x => Data.fold R.transform x.tail x.head
charge := _
routine := R.routine.fold
correct x := fold_correct R x.1 x.2
def foldTime {F : α × β → β} (R : Realizer F) (b : β) : List α → ℕ
| [] => 1
| a :: xs => R.time (a,b)+foldTime R (F (a,b)) xs+
20*(volume (a :: xs)+volume b+volume (F (a,b))+1)
theorem foldTime_eq {F : α × β → β} (R : Realizer F) (xs : List α) (b : β) :
Data.foldCost R.transform R.charge (enc b) (enc xs) = foldTime R b xs := by
induction xs generalizing b with
| nil => rfl
| cons a xs ih =>
change R.time (a,b)+Data.foldCost R.transform R.charge (R.transform (enc (a,b))) (enc xs)+
20*(volume (a :: xs)+volume b+(R.transform (enc (a,b))).size+1) = _
rw [R.correct,ih]
rfl
theorem time_fold {F : α × β → β} (R : Realizer F) (x : List α × β) :
R.fold.time x = 2*volume x+6+foldTime R x.2 x.1 := by
change 2*volume x+6+Data.foldCost R.transform R.charge (enc x.2) (enc x.1) = _
rw [foldTime_eq]
end Realizer
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Tree
variable {V : Type} [DecidableEq V]
theorem Bounded.branch_true {src : V} {p q : Code V} {s t : V → Data} {n : ℕ}
(h : (s src).nonempty = true) (hp : Bounded p s t n) : Bounded (.branch src p q) s t (n+1) := by
obtain ⟨m,hm,he⟩ := hp
exact ⟨m+1,by omega,Eval.branch_true h he⟩
theorem Bounded.branch_false {src : V} {p q : Code V} {s t : V → Data} {n : ℕ}
(h : (s src).nonempty = false) (hq : Bounded q s t n) : Bounded (.branch src p q) s t (n+1) := by
obtain ⟨m,hm,he⟩ := hq
exact ⟨m+1,by omega,Eval.branch_false h he⟩
end ThreeMachine.StackCompiler.Tree
namespace ThreeMachine.StackCompiler
open ThreeMachine.StackCompiler.Tree
namespace Routine
variable {f g : Data → Data} {c d : Data → ℕ}
variable {V : Type} [DecidableEq V]
def invoke (R : Routine f c) (dst src : V) : Code (V ⊕ R.Vars) :=
.seq (.copy (.inr R.input) (.inl src))
(.seq (R.code.rename Sum.inr)
(.seq (.copy (.inl dst) (.inr R.output))
(.seq (.nil (.inr R.input)) (.nil (.inr R.output)))))
theorem invoke_correct (R : Routine f c) (dst src : V) (s : V → Data) :
Bounded (R.invoke dst src) (join s (zeroStore R.Vars))
(join (Function.update s dst (f (s src))) (zeroStore R.Vars))
(c (s src)+10*((s src).size+(s dst).size+(f (s src)).size+1)) := by
let a := start R.input (s src)
let b := finish R.input R.output (s src) (f (s src))
let t := Function.update s dst (f (s src))
have h₁ : Bounded (.copy (.inr R.input) (.inl src))
(join s (zeroStore R.Vars)) (join s a) (2+(s src).size) := by
simpa [join_update_right,a,start,zeroStore] using
(Eval.copy (.inr R.input) (.inl src) (join s (zeroStore R.Vars))).bounded
have h₂ := (R.correct (s src)).right s
have h₃ : Bounded (.copy (.inl dst) (.inr R.output)) (join s b) (join t b)
(1+(s dst).size+(f (s src)).size) := by
simpa [join_update_left,t,b] using (Eval.copy (.inl dst) (.inr R.output) (join s b)).bounded
have h₄ : Bounded (.nil (.inr R.input)) (join t b)
(join t (start R.output (f (s src)))) (1+(s src).size) := by
simpa only [join_update_right,b,reset_input R.distinct,join_inr,finish_input R.distinct] using
(Eval.nil (.inr R.input) (join t b)).bounded
have h₅ : Bounded (.nil (.inr R.output)) (join t (start R.output (f (s src))))
(join t (zeroStore R.Vars)) (1+(f (s src)).size) := by
simpa only [join_update_right,reset_start,join_inr,start_input] using
(Eval.nil (.inr R.output) (join t (start R.output (f (s src))))).bounded
exact (h₁.seq (h₂.seq (h₃.seq (h₄.seq h₅)))).mono (by omega)
def chooseCode (R : Routine f c) (S : Routine g d) : Code ((Fin 3 ⊕ R.Vars) ⊕ S.Vars) :=
.seq (.select true (.inl (.inl 2)) (.inl (.inl 0)))
(.seq (.branch (.inl (.inl 2))
((R.invoke (1 : Fin 3) 0).rename Sum.inl)
(S.invoke (Sum.inl (1 : Fin 3)) (Sum.inl 0)))
(.nil (.inl (.inl 2))))
def choose (R : Routine f c) (S : Routine g d) :
Routine (fun x => if x.head.nonempty then f x else g x)
(fun x => c x+d x+30*(x.size+(f x).size+(g x).size+1)) where
Vars := (Fin 3 ⊕ R.Vars) ⊕ S.Vars
finiteVars := inferInstance
decVars := inferInstance
input := .inl (.inl 0)
output := .inl (.inl 1)
distinct := by simp
code := chooseCode R S
correct x := by
let z := zeroStore R.Vars
let w := zeroStore S.Vars
let s := foldStore x .nil .nil
let s' := foldStore x .nil x.head
let y := if x.head.nonempty then f x else g x
let t := foldStore x y x.head
have es : start (0 : Fin 3) x = s := by
funext i; fin_cases i <;> simp [s,start,zeroStore,foldStore]
have ef : finish (Sum.inl (Sum.inl (0 : Fin 3))) (Sum.inl (Sum.inl (1 : Fin 3))) x y =
join (join (foldStore x y .nil) z) w := by
rw [finish,start_left,start_left,es,join_update_left,join_update_left]
simp only [s,foldStore_update_one]
rfl
have h₁ : Bounded (.select true (.inl (.inl 2)) (.inl (.inl 0)))
(join (join s z) w) (join (join s' z) w) (2+x.size) := by
simpa [join_update_left,s,s',foldStore_update_two] using
(Eval.select true (.inl (.inl 2)) (.inl (.inl 0)) (join (join s z) w)).bounded
have h₂ : Bounded (.branch (.inl (.inl 2)) ((R.invoke (1 : Fin 3) 0).rename Sum.inl)
(S.invoke (Sum.inl (1 : Fin 3)) (Sum.inl 0)))
(join (join s' z) w) (join (join t z) w)
(c x+d x+10*(x.size+(f x).size+(g x).size+2)+1) := by
cases he : x.head.nonempty with
| false =>
have hh := (S.invoke_correct (Sum.inl (1 : Fin 3)) (Sum.inl 0) (join s' z)).branch_false
(src := Sum.inl (Sum.inl (2 : Fin 3))) (p := ((R.invoke (1 : Fin 3) 0).rename Sum.inl)) (by simpa [s'] using he)
simpa only [join_update_left,s',foldStore_update_one,t,y,he,Bool.false_eq_true,ite_false,join_inl,foldStore_zero] using
(hh.mono (m := c x+d x+10*(x.size+(f x).size+(g x).size+2)+1)
(by simp only [join_inl,foldStore_zero,foldStore_one,s',Data.size_nil]; omega))
| true =>
have hh := ((R.invoke_correct (1 : Fin 3) 0 s').left w).branch_true
(src := Sum.inl (Sum.inl (2 : Fin 3))) (q := S.invoke (Sum.inl (1 : Fin 3)) (Sum.inl 0)) (by simpa [s'] using he)
simpa only [s',foldStore_update_one,t,y,he,ite_true,foldStore_zero] using
(hh.mono (m := c x+d x+10*(x.size+(f x).size+(g x).size+2)+1)
(by simp only [foldStore_zero,foldStore_one,s',Data.size_nil]; omega))
have h₃ : Bounded (.nil (.inl (.inl 2))) (join (join t z) w)
(join (join (foldStore x y .nil) z) w) (1+x.head.size) := by
simpa only [join_update_left,t,foldStore_update_two,join_inl,foldStore_two] using
(Eval.nil (.inl (.inl 2)) (join (join t z) w)).bounded
rw [start_left,start_left,es,ef]
have hh := h₁.seq (h₂.seq h₃)
exact hh.mono (by
have hx : x.head.size ≤ x.size := by cases x <;> simp [Data.head]; omega
omega)
end Routine
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
namespace Routine
def constant : (d : Data) → Routine (fun _ => d) (fun x => (2*d.size+1)*(20*x.size+50*d.size+50))
| .nil => nil.mono (by intro x; simp only [Data.size_nil]; omega)
| .pair a b => ((constant a).pair (constant b)).mono (by
intro x
simp only [Data.size_pair]
nlinarith)
end Routine
namespace Realizer
variable {α : Type u25} {β : Type u26} {γ : Type u27} [Coding α] [Coding β] [Coding γ]
def constant (b : β) : Realizer (fun _ : α => b) :=
⟨fun _ => enc b,_,Routine.constant (enc b),fun _ => rfl⟩
def reinterpret (f : α → β) (h : ∀ x, enc (f x) = enc x) : Realizer f :=
⟨_root_.id,_,Routine.identity,fun x => (h x).symm⟩
@[simp] theorem time_reinterpret (f : α → β) (h : ∀ x, enc (f x) = enc x) (x : α) :
(reinterpret f h).time x = volume x+2 := rfl
def cons : Realizer (fun x : α × List α => x.1 :: x.2) := reinterpret _ (fun _ => rfl)
def choose {f g : α → β} (R : Realizer f) (S : Realizer g) :
Realizer (fun x : Bool × α => if x.1 then f x.2 else g x.2) where
transform := fun x => if x.head.nonempty then (snd.comp R).transform x else (snd.comp S).transform x
charge := _
routine := (snd.comp R).routine.choose (snd.comp S).routine
correct x := by
rcases x with ⟨b,x⟩
cases b <;> simp only [enc_pair,enc_false,enc_true,Data.head,Data.nonempty,
Bool.false_eq_true,ite_false,ite_true]
· exact (snd.comp S).correct (Bool.false,x)
· exact (snd.comp R).correct (true,x)
theorem time_choose {f g : α → β} (R : Realizer f) (S : Realizer g) (x : Bool × α) :
(R.choose S).time x = (snd.comp R).time x+(snd.comp S).time x+
30*(volume x+volume (f x.2)+volume (g x.2)+1) := by
change (snd.comp R).time x+(snd.comp S).time x+
30*(volume x+((snd.comp R).transform (enc x)).size+((snd.comp S).transform (enc x)).size+1) = _
rw [(snd.comp R).correct,(snd.comp S).correct]
rfl
def succ : Realizer (fun n : ℕ => n+1) :=
(unit.pair id).comp (reinterpret (fun x : Unit × ℕ => x.2+1) (by intro x; rfl)) |>.congr (fun _ => rfl)
end Realizer
end ThreeMachine.StackCompiler
end
end OAI
end
section
-- module UniformRoutines
namespace OAI
universe u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16 u17 u18 u19 u20 u21 u22 u23 u24 u25 u26
section
namespace ThreeMachine.StackCompiler
variable {α : Type u1} {β : Type u2} [Coding α] [Coding β]
theorem volume_pos (x : α) : 0 < volume x := by
change 0 < (enc x).encode.length
cases enc x <;> simp [Data.encode]
theorem volume_list_le (xs : List α) (M : ℕ) (h : ∀ a ∈ xs, volume a ≤ M) :
volume xs ≤ xs.length*(M+1)+1 := by
induction xs with
| nil => simp
| cons a xs ih =>
have ha := h a (by simp)
have ht := ih (fun a ha => h a (by simp [ha]))
simp only [volume_cons,List.length_cons]
nlinarith
namespace Realizer
variable {F : α × β → β}
end Realizer
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Realizer
variable {α : Type u3} {β : Type u4} {γ : Type u5} [Coding α] [Coding β] [Coding γ]
def onFst {f : α → β} (R : Realizer f) : Realizer (fun x : α × γ => (f x.1,x.2)) :=
(fst.comp R).pair snd
def swap : Realizer (fun x : α × β => (x.2,x.1)) := snd.pair fst
omit [Coding α] in
theorem fold_cons_eq (xs ys : List α) :
xs.foldl (fun ys a => a :: ys) ys = xs.reverse ++ ys := by
induction xs generalizing ys with
| nil => simp
| cons a xs ih => simp [ih,List.append_assoc]
def reverse : Realizer (fun xs : List α => xs.reverse) :=
((id.pair (nil : Realizer (fun _ : List α => ([] : List α)))).comp cons.fold).congr
(fun xs => by simp only [Function.comp_apply,fold_cons_eq,List.append_nil,id_eq])
omit [Coding α] [Coding β] [Coding γ] in
theorem map_fold_eq (f : α × γ → β) (xs : List α) (e : γ) (ys : List β) :
xs.foldl (fun s a => (s.1,f (a,s.1) :: s.2)) (e,ys) =
(e,(xs.map (fun a => f (a,e))).reverse ++ ys) := by
induction xs generalizing ys with
| nil => simp
| cons a xs ih => simp [ih,List.append_assoc]
end ThreeMachine.StackCompiler.Realizer
namespace ThreeMachine.StackCompiler
structure Uniform {I : Type u6} {α : I → Type u7} {β : I → Type u8} [∀ i, Coding (α i)] [∀ i, Coding (β i)]
(f : ∀ i, α i → β i) where
transform : Data → Data
charge : Data → ℕ
routine : Routine transform charge
correct : ∀ i x, transform (enc x) = enc (f i x)
namespace Uniform
variable {I : Type u9} {α : I → Type u10} {β : I → Type u11} {γ : I → Type u12} {δ : I → Type u13}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)] [∀ i, Coding (δ i)]
variable {f : ∀ i, α i → β i} {g : ∀ i, β i → γ i}
def specialize (R : Uniform f) (i : I) : Realizer (f i) :=
⟨R.transform,R.charge,R.routine,R.correct i⟩
def time (R : Uniform f) (i : I) (x : α i) : ℕ := R.charge (enc x)
def id : Uniform (fun (i : I) (x : α i) => x) :=
⟨_root_.id,_,Routine.identity,fun _ _ => rfl⟩
def unit : Uniform (fun (i : I) (_ : α i) => ()) :=
⟨fun _ => .nil,_,Routine.nil,fun _ _ => rfl⟩
def nil : Uniform (fun (i : I) (_ : α i) => ([] : List (β i))) :=
⟨fun _ => .nil,_,Routine.nil,fun _ _ => rfl⟩
def zero : Uniform (fun (i : I) (_ : α i) => (0 : ℕ)) :=
⟨fun _ => .nil,_,Routine.nil,fun _ _ => rfl⟩
def false : Uniform (fun (i : I) (_ : α i) => Bool.false) :=
⟨fun _ => .nil,_,Routine.nil,fun _ _ => rfl⟩
def comp (R : Uniform f) (S : Uniform g) : Uniform (fun i => g i ∘ f i) where
transform := S.transform ∘ R.transform
charge := _
routine := R.routine.comp S.routine
correct i x := by simp only [Function.comp_apply,R.correct,S.correct]
def pair {g : ∀ i, α i → γ i} (R : Uniform f) (S : Uniform g) :
Uniform (fun i x => (f i x,g i x)) where
transform := fun x => .pair (R.transform x) (S.transform x)
charge := _
routine := R.routine.pair S.routine
correct i x := by simp only [R.correct,S.correct,enc_pair]
def fst : Uniform (fun (i : I) => (Prod.fst : α i × β i → α i)) :=
⟨Data.head,_,Routine.select true,fun _ _ => rfl⟩
def snd : Uniform (fun (i : I) => (Prod.snd : α i × β i → β i)) :=
⟨Data.tail,_,Routine.select Bool.false,fun _ _ => rfl⟩
def congr {f' : ∀ i, α i → β i} (R : Uniform f) (h : ∀ i x, f i x = f' i x) : Uniform f' :=
{ R with correct := fun i x => (R.correct i x).trans (congrArg enc (h i x)) }
def reinterpret (f : ∀ i, α i → β i) (h : ∀ i x, enc (f i x) = enc x) : Uniform f :=
⟨_root_.id,_,Routine.identity,fun i x => (h i x).symm⟩
def fold {F : ∀ i, α i × β i → β i} (R : Uniform F) :
Uniform (fun i (x : List (α i) × β i) => x.1.foldl (fun b a => F i (a,b)) x.2) where
transform := fun x => Data.fold R.transform x.tail x.head
charge := _
routine := R.routine.fold
correct i x := (R.specialize i).fold_correct x.1 x.2
def choose {g : ∀ i, α i → β i} (R : Uniform f) (S : Uniform g) :
Uniform (fun i (x : Bool × α i) => if x.1 then f i x.2 else g i x.2) where
transform := fun x => if x.head.nonempty then ((snd (α := fun _ : I => Bool) (β := α)).comp R).transform x else ((snd (α := fun _ : I => Bool) (β := α)).comp S).transform x
charge := _
routine := ((snd (α := fun _ : I => Bool) (β := α)).comp R).routine.choose ((snd (α := fun _ : I => Bool) (β := α)).comp S).routine
correct i x := ((R.specialize i).choose (S.specialize i)).correct x
def ite {p : ∀ i, α i → Bool} {g : ∀ i, α i → β i}
(P : Uniform p) (R : Uniform f) (S : Uniform g) :
Uniform (fun i x => if p i x then f i x else g i x) :=
((P.pair id).comp (R.choose S)).congr (fun _ _ => rfl)
def cons : Uniform (fun (i : I) (x : α i × List (α i)) => x.1 :: x.2) := reinterpret _ (fun _ _ => rfl)
def onFst (R : Uniform f) : Uniform (fun i (x : α i × γ i) => (f i x.1,x.2)) :=
(fst.comp R).pair snd
def reverse : Uniform (fun (i : I) (xs : List (α i)) => xs.reverse) :=
((id.pair (nil : Uniform (fun (i : I) (_ : List (α i)) => ([] : List (α i))))).comp cons.fold).congr
(fun _ _ => by simp only [Function.comp_apply,Realizer.fold_cons_eq,List.append_nil])
def mapBody {f : ∀ i, α i × γ i → β i} (R : Uniform f) :
Uniform (fun i (x : α i × (γ i × List (β i))) => (x.2.1,f i (x.1,x.2.1) :: x.2.2)) :=
(snd.comp fst).pair ((((fst.pair (snd.comp fst)).comp R).pair (snd.comp snd)).comp cons)
def map {f : ∀ i, α i × γ i → β i} (R : Uniform f) :
Uniform (fun i (x : List (α i) × γ i) => x.1.map (fun a => f i (a,x.2))) :=
(((fst.pair (snd.pair nil)).comp (mapBody R).fold).comp (snd.comp reverse)).congr (fun _ _ => by
simp only [Function.comp_apply,Realizer.map_fold_eq,List.append_nil,List.reverse_reverse])
end Uniform
namespace Realizer
variable {α : Type u14} {β : Type u15} [Coding α] [Coding β] {f : α → β}
def uniform (R : Realizer f) (I : Type u16) : Uniform (fun (_ : I) => f) :=
⟨R.transform,R.charge,R.routine,fun _ => R.correct⟩
end Realizer
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
namespace Realizer
variable {α : Type u17} [Coding α]
def test (p : α → Bool) (h : ∀ x, (enc x).nonempty = p x) : Realizer p where
transform := fun x => if x.nonempty then .pair .nil .nil else .nil
charge := _
routine := (Routine.identity.pair Routine.nil).comp
((Routine.constant (.pair .nil .nil)).choose Routine.nil)
correct x := by rw [h]; cases p x <;> rfl
def not : Realizer Bool.not :=
((id.pair unit).comp ((false : Realizer (fun _ : Unit => Bool.false)).choose (constant true))).congr
(fun b => by cases b <;> rfl)
def and : Realizer (fun x : Bool × Bool => x.1 && x.2) :=
(id.choose false).congr (fun x => by rcases x with ⟨a,b⟩; cases a <;> rfl)
def or : Realizer (fun x : Bool × Bool => x.1 || x.2) :=
((constant true).choose id).congr (fun x => by rcases x with ⟨a,b⟩; cases a <;> rfl)
def positive : Realizer (fun n : ℕ => decide (0 < n)) :=
test _ (by intro n; cases n <;> rfl)
def isZero : Realizer (fun n : ℕ => decide (n = 0)) :=
(positive.comp not).congr (fun n => by cases n <;> rfl)
def pred : Realizer Nat.pred :=
⟨Data.tail,_,Routine.select Bool.false,fun n => by cases n <;> rfl⟩
theorem encode_replicate_unit (n : ℕ) : enc (List.replicate n ()) = enc n := by
induction n with
| zero => rfl
| succ n ih => simp only [List.replicate_succ,enc_cons,enc_unit,ih,enc_succ]
def unroll : Realizer (fun n : ℕ => List.replicate n ()) :=
reinterpret _ encode_replicate_unit
omit [Coding α] in
theorem fold_replicate (f : α → α) (n : ℕ) (a : α) :
(List.replicate n ()).foldl (fun a _ => f a) a = f^[n] a := by
induction n generalizing a with
| zero => rfl
| succ n ih => simpa only [List.replicate_succ,List.foldl_cons,Function.iterate_succ_apply] using ih (f a)
def iterate {f : α → α} (R : Realizer f) : Realizer (fun x : ℕ × α => f^[x.1] x.2) :=
(unroll.onFst.comp (snd.comp R).fold).congr (fun x => fold_replicate f x.1 x.2)
theorem iterate_pred (n m : ℕ) : Nat.pred^[n] m = m-n := by
induction n generalizing m with
| zero => rfl
| succ n ih => rw [Function.iterate_succ_apply,ih,Nat.pred_eq_sub_one]; omega
theorem iterate_succ (n m : ℕ) : (fun k : ℕ => k+1)^[n] m = m+n := by
induction n generalizing m with
| zero => rfl
| succ n ih => rw [Function.iterate_succ_apply,ih]; omega
def add : Realizer (fun x : ℕ × ℕ => x.1+x.2) :=
succ.iterate.congr (fun x => by rw [iterate_succ,Nat.add_comm])
def sub : Realizer (fun x : ℕ × ℕ => x.1-x.2) :=
(swap.comp pred.iterate).congr (fun x => iterate_pred x.2 x.1)
def le : Realizer (fun x : ℕ × ℕ => decide (x.1 ≤ x.2)) :=
(sub.comp isZero).congr (fun x => by simp only [Function.comp_apply,Nat.sub_eq_zero_iff_le])
def eqNat : Realizer (fun x : ℕ × ℕ => decide (x.1 = x.2)) :=
((le.pair (swap.comp le)).comp and).congr (fun x => by
apply Bool.eq_iff_iff.mpr
simp [le_antisymm_iff])
end Realizer
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Uniform
variable {I : Type u18} {α : I → Type u19} {β : I → Type u20} {γ : I → Type u21}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
def test (p : ∀ i, α i → Bool) (h : ∀ i x, (enc x).nonempty = p i x) : Uniform p where
transform := fun x => if x.nonempty then .pair .nil .nil else .nil
charge := _
routine := (Routine.identity.pair Routine.nil).comp
((Routine.constant (.pair .nil .nil)).choose Routine.nil)
correct i x := by rw [h]; cases p i x <;> rfl
def isCons : Uniform (fun (i : I) (xs : List (α i)) => !xs.isEmpty) :=
test _ (by intro _ xs; cases xs <;> rfl)
def head? : Uniform (fun (i : I) (xs : List (α i)) => xs.head?) where
transform := fun x => if x.nonempty then .pair x.head .nil else .nil
charge := _
routine := (Routine.identity.pair Routine.nil).comp
((((Routine.select true).comp (Routine.select true)).pair Routine.nil).choose Routine.nil)
correct i xs := by cases xs <;> rfl
def swap : Uniform (fun (i : I) (x : α i × β i) => (x.2,x.1)) := snd.pair fst
def append : Uniform (fun (i : I) (x : List (α i) × List (α i)) => x.1 ++ x.2) :=
(((fst.comp reverse).pair snd).comp cons.fold).congr (fun _ _ => by
simp only [Function.comp_apply,Realizer.fold_cons_eq,List.reverse_reverse])
omit [∀ i, Coding (α i)] in
theorem flatten_fold_eq (i : I) (xs : List (List (α i))) (acc : List (α i)) :
xs.foldl (fun ys zs => zs.foldl (fun ys a => a :: ys) ys) acc = xs.flatten.reverse ++ acc := by
induction xs generalizing acc with
| nil => simp
| cons xs xss ih =>
rw [List.foldl_cons,ih,Realizer.fold_cons_eq]
simp only [List.flatten_cons,List.reverse_append,List.append_assoc]
def flatten : Uniform (fun (i : I) (xs : List (List (α i))) => xs.flatten) :=
(((id.pair nil).comp cons.fold.fold).comp reverse).congr (fun _ _ => by
simp only [Function.comp_apply,flatten_fold_eq,List.append_nil,List.reverse_reverse])
def flatMap {f : ∀ i, α i × γ i → List (β i)} (R : Uniform f) :
Uniform (fun i (x : List (α i) × γ i) => x.1.flatMap (fun a => f i (a,x.2))) :=
(R.map.comp flatten).congr (fun _ _ => rfl)
def filterBody {p : ∀ i, α i × γ i → Bool} (P : Uniform p) :
Uniform (fun i (x : α i × (γ i × List (α i))) =>
(x.2.1,if p i (x.1,x.2.1) then x.1 :: x.2.2 else x.2.2)) :=
(snd.comp fst).pair
(((fst.pair (snd.comp fst)).comp P).ite ((fst.pair (snd.comp snd)).comp cons) (snd.comp snd))
omit [∀ i, Coding (α i)] [∀ i, Coding (γ i)] in
theorem filter_fold_eq (p : ∀ i, α i × γ i → Bool) (i : I)
(xs : List (α i)) (e : γ i) (ys : List (α i)) :
xs.foldl (fun s a => (s.1,if p i (a,s.1) then a :: s.2 else s.2)) (e,ys) =
(e,(xs.filter (fun a => p i (a,e))).reverse ++ ys) := by
induction xs generalizing ys with
| nil => simp
| cons a xs ih =>
cases he : p i (a,e) <;> simp [he,ih,List.append_assoc]
def filter {p : ∀ i, α i × γ i → Bool} (P : Uniform p) :
Uniform (fun i (x : List (α i) × γ i) => x.1.filter (fun a => p i (a,x.2))) :=
(((fst.pair (snd.pair nil)).comp (filterBody P).fold).comp (snd.comp reverse)).congr (fun _ _ => by
simp only [Function.comp_apply,filter_fold_eq,List.append_nil,List.reverse_reverse])
def optionToList : Uniform (fun (i : I) (x : Option (α i)) => x.toList) :=
reinterpret _ (by intro i x; cases x <;> rfl)
def filterMap {f : ∀ i, α i × γ i → Option (β i)} (R : Uniform f) :
Uniform (fun i (x : List (α i) × γ i) => x.1.filterMap (fun a => f i (a,x.2))) :=
(R.comp optionToList).flatMap.congr (fun i x => by
induction x.1 with
| nil => rfl
| cons a xs ih =>
simp only [List.flatMap_cons,List.filterMap_cons]
cases he : f i (a,x.2) <;> simp_all)
def optionMap {f : ∀ i, α i × γ i → β i} (R : Uniform f) :
Uniform (fun i (x : Option (α i) × γ i) => x.1.map (fun a => f i (a,x.2))) :=
((optionToList.onFst.comp R.map).comp head?).congr (fun i x => by
rcases x with ⟨o,e⟩
cases o <;> rfl)
end ThreeMachine.StackCompiler.Uniform
namespace ThreeMachine.StackCompiler.Uniform
variable {I : Type u22} {α : I → Type u23} {β : I → Type u24} {γ : I → Type u25}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
def constant {δ : Type u26} [Coding δ] (a : δ) :
Uniform (fun (i : I) (_ : α i) => a) where
transform := fun _ => enc a
charge := _
routine := Routine.constant (enc a)
correct _ _ := rfl
def some : Uniform (fun (i : I) (a : α i) => Option.some a) where
transform := fun x => .pair x .nil
charge := _
routine := Routine.identity.pair Routine.nil
correct _ _ := rfl
def none : Uniform (fun (i : I) (_ : α i) => (Option.none : Option (β i))) :=
⟨fun _ => .nil,_,Routine.nil,fun _ _ => rfl⟩
def optionIsSome : Uniform (fun (i : I) (x : Option (α i)) => x.isSome) :=
test _ (by intro _ x; cases x <;> rfl)
def getD : Uniform (fun (i : I) (x : Option (α i) × α i) => x.1.getD x.2) :=
(((fst.comp optionToList).pair snd).comp fst.fold).congr (fun _ x => by
rcases x with ⟨o,a⟩; cases o <;> rfl)
def length : Uniform (fun (i : I) (xs : List (α i)) => xs.length) :=
((id.pair zero).comp (snd.comp (Realizer.succ.uniform I)).fold).congr (fun i xs => by
have h : ∀ (ys : List (α i)) (n : ℕ),
ys.foldl (fun n _ => n+1) n = n+ys.length := by
intro ys; induction ys with
| nil => intro n; simp
| cons a ys ih => intro n; simp [ih]; omega
simpa only [Function.comp_apply,Nat.zero_add] using h xs 0)
def iterate {f : ∀ i, α i → α i} (R : Uniform f) :
Uniform (fun i (x : ℕ × α i) => (f i)^[x.1] x.2) :=
((Realizer.unroll.uniform I).onFst.comp (snd.comp R).fold).congr (fun i x =>
Realizer.fold_replicate (f i) x.1 x.2)
def anyBody {p : ∀ i, α i × γ i → Bool} (P : Uniform p) :
Uniform (fun i (x : α i × (γ i × Bool)) =>
(x.2.1,x.2.2 || p i (x.1,x.2.1))) :=
(snd.comp fst).pair
(((snd.comp snd).pair ((fst.pair (snd.comp fst)).comp P)).comp (Realizer.or.uniform I))
omit [∀ i, Coding (α i)] [∀ i, Coding (γ i)] in
theorem any_fold_eq (p : ∀ i, α i × γ i → Bool) (i : I)
(xs : List (α i)) (e : γ i) (b : Bool) :
xs.foldl (fun s a => (s.1,s.2 || p i (a,s.1))) (e,b) =
(e,b || xs.any (fun a => p i (a,e))) := by
induction xs generalizing b with
| nil => simp
| cons a xs ih => simp [ih,Bool.or_assoc]
def any {p : ∀ i, α i × γ i → Bool} (P : Uniform p) :
Uniform (fun i (x : List (α i) × γ i) => x.1.any (fun a => p i (a,x.2))) :=
(((fst.pair (snd.pair false)).comp (anyBody P).fold).comp snd).congr (fun _ _ => by
simp only [Function.comp_apply,any_fold_eq,Bool.false_or])
def all {p : ∀ i, α i × γ i → Bool} (P : Uniform p) :
Uniform (fun i (x : List (α i) × γ i) => x.1.all (fun a => p i (a,x.2))) :=
((P.comp (Realizer.not.uniform I)).any.comp (Realizer.not.uniform I)).congr (fun _ x => by
simp only [Function.comp_apply,List.all_eq_not_any_not])
def find? {p : ∀ i, α i × γ i → Bool} (P : Uniform p) :
Uniform (fun i (x : List (α i) × γ i) => x.1.find? (fun a => p i (a,x.2))) :=
(P.filter.comp head?).congr (fun _ x => by
dsimp only [Function.comp_apply]
induction x.1 with
| nil => rfl
| cons a xs ih => cases he : p _ (a,x.2) <;> simp_all)
def firstResult {f : ∀ i, α i × γ i → Option (β i)} (R : Uniform f) :
Uniform (fun i (x : List (α i) × γ i) => (x.1.filterMap (fun a => f i (a,x.2))).head?) :=
R.filterMap.comp head?
def tableOf {f : ∀ i, α i × γ i → Option (β i)} (R : Uniform f) :
Uniform (fun i (x : List (α i) × γ i) =>
x.1.filterMap (fun a => (f i (a,x.2)).map (fun b => (a,b)))) :=
((R.pair fst).comp ((swap : Uniform (fun i (x : β i × α i) => (x.2,x.1))).optionMap)).filterMap
end ThreeMachine.StackCompiler.Uniform
end
end OAI
end
section
-- module FiniteRoutines
namespace OAI
universe u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15
section
namespace ThreeMachine.StackCompiler
instance (n : ℕ) : Coding (Fin n) := ⟨fun x => enc x.val⟩
instance (n : ℕ) : Coding (Finset (Fin n)) := ⟨fun s => enc (s.sort (· ≤ ·))⟩
@[simp] theorem enc_fin {n : ℕ} (x : Fin n) : enc x = enc x.val := rfl
@[simp] theorem volume_fin {n : ℕ} (x : Fin n) : volume x = 2*x.val+1 := volume_nat x.val
@[simp] theorem enc_finset {n : ℕ} (s : Finset (Fin n)) :
enc s = enc (s.sort (· ≤ ·)) := rfl
structure Cardinal (n : ℕ) where
trivial : Unit
instance (n : ℕ) : Coding (Cardinal n) := ⟨fun _ => enc n⟩
structure Universe (n : ℕ) where
trivial : Unit
instance (n : ℕ) : Coding (Universe n) := ⟨fun _ => enc (List.finRange n)⟩
theorem enc_list_map {α : Type u1} {β : Type u2} [Coding α] [Coding β] (f : α → β)
(hf : ∀ x, enc (f x) = enc x) (xs : List α) : enc (xs.map f) = enc xs := by
induction xs with
| nil => rfl
| cons a xs ih => simp only [List.map_cons,enc_cons,hf,ih]
theorem sort_filter {n : ℕ} (s : Finset (Fin n)) (p : Fin n → Bool) :
(s.filter (fun x => p x)).sort (· ≤ ·) = (s.sort (· ≤ ·)).filter p := by
have he : ((s.sort (· ≤ ·)).filter p).toFinset = s.filter (fun x => p x) := by
ext x; simp
rw [← he]
exact (List.toFinset_sort (· ≤ ·) ((s.sort_nodup (· ≤ ·)).filter p)).mpr
((s.pairwise_sort (· ≤ ·)).filter p)
namespace Uniform
def finVal : Uniform (fun n (x : Fin n) => x.val) := reinterpret _ (fun _ _ => rfl)
def finEq : Uniform (fun n (x : Fin n × Fin n) => decide (x.1 = x.2)) :=
(((fst.comp finVal).pair (snd.comp finVal)).comp (Realizer.eqNat.uniform ℕ)).congr
(fun _ x => by simp only [Function.comp_apply,Fin.val_inj])
def universeList : Uniform (fun n (_ : Universe n) => List.finRange n) :=
reinterpret _ (fun _ _ => rfl)
def universeSet : Uniform (fun n (_ : Universe n) => (Finset.univ : Finset (Fin n))) :=
reinterpret _ (fun n _ => by simp only [enc_finset,Fin.sort_univ]; rfl)
def setList : Uniform (fun n (s : Finset (Fin n)) => s.sort (· ≤ ·)) :=
reinterpret _ (fun _ _ => rfl)
def setEmpty : Uniform (fun n (_ : Universe n) => (∅ : Finset (Fin n))) where
transform := fun _ => .nil
charge := _
routine := Routine.nil
correct _ _ := by simp only [enc_finset,Finset.sort_empty]; rfl
def setIsEmpty : Uniform (fun n (s : Finset (Fin n)) => decide (s = ∅)) :=
((setList.comp isCons).comp (Realizer.not.uniform ℕ)).congr (fun _ x => by
by_cases h : x = ∅
· subst x; simp
· have hh : x.sort (· ≤ ·) ≠ [] := by
intro he; have := congrArg List.toFinset he
exact h (by simpa only [Finset.sort_toFinset,List.toFinset_nil] using this)
simp [Function.comp_apply,List.isEmpty_eq_false_iff,hh,h])
def setCard : Uniform (fun n (s : Finset (Fin n)) => s.card) :=
(setList.comp length).congr (fun _ _ => Finset.length_sort (· ≤ ·))
def setFilter {γ : ℕ → Type u3} [∀ n, Coding (γ n)]
{p : ∀ n, Fin n × γ n → Bool} (P : Uniform p) :
Uniform (fun n (x : Finset (Fin n) × γ n) => x.1.filter (fun a => p n (a,x.2))) where
transform := (setList.onFst.comp P.filter).transform
charge := (setList.onFst.comp P.filter).charge
routine := (setList.onFst.comp P.filter).routine
correct n x := by
rw [(setList.onFst.comp P.filter).correct]
simp only [Function.comp_apply,enc_finset,sort_filter]
def setMem : Uniform (fun n (x : Fin n × Finset (Fin n)) => decide (x.1 ∈ x.2)) :=
((((snd.comp setList).pair fst).comp finEq.any)).congr (fun _ x => by
apply Bool.eq_iff_iff.mpr
simp only [Function.comp_apply,List.any_eq_true,decide_eq_true_eq]
simp)
def setInter : Uniform (fun n (x : Finset (Fin n) × Finset (Fin n)) => x.1 ∩ x.2) :=
setMem.setFilter.congr (fun _ x => by ext a; simp)
def setDiff : Uniform (fun n (x : Finset (Fin n) × Finset (Fin n)) => x.1 \ x.2) :=
(setMem.comp (Realizer.not.uniform ℕ)).setFilter.congr (fun _ x => by ext a; simp)
def setSubset : Uniform (fun n (x : Finset (Fin n) × Finset (Fin n)) => decide (x.1 ⊆ x.2)) :=
((setList.onFst).comp setMem.all).congr (fun _ x => by
apply Bool.eq_iff_iff.mpr
simp only [Function.comp_apply,List.all_eq_true,decide_eq_true_eq,Finset.mem_sort]
rfl)
def setEq : Uniform (fun n (x : Finset (Fin n) × Finset (Fin n)) => decide (x.1 = x.2)) :=
((setSubset.pair (swap.comp setSubset)).comp (Realizer.and.uniform ℕ)).congr (fun _ x => by
apply Bool.eq_iff_iff.mpr
simp [Finset.Subset.antisymm_iff])
def setDisjoint : Uniform (fun n (x : Finset (Fin n) × Finset (Fin n)) => decide (Disjoint x.1 x.2)) :=
(setInter.comp setIsEmpty).congr (fun _ x => by
simp only [Function.comp_apply,Finset.disjoint_iff_inter_eq_empty])
def setUnionBody : Uniform (fun n (x : Fin n × (Finset (Fin n) × Finset (Fin n))) =>
decide (x.1 ∈ x.2.1 ∨ x.1 ∈ x.2.2)) :=
((((fst.pair (snd.comp fst)).comp setMem).pair
((fst.pair (snd.comp snd)).comp setMem)).comp (Realizer.or.uniform ℕ)).congr (fun _ _ => by simp)
def setUnion : Uniform (fun n (x : Universe n × (Finset (Fin n) × Finset (Fin n))) =>
x.2.1 ∪ x.2.2) :=
(((fst.comp universeSet).pair snd).comp setUnionBody.setFilter).congr (fun _ x => by
ext a; simp)
def setCompl : Uniform (fun n (x : Universe n × Finset (Fin n)) => x.2ᶜ) :=
(((fst.comp universeSet).pair snd).comp setDiff).congr (fun _ x => (Finset.compl_eq_univ_sdiff x.2).symm)
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
namespace Realizer
def rangeStep : Realizer (fun x : ℕ × List ℕ => (x.1+1,x.1 :: x.2)) :=
(fst.comp succ).pair cons
theorem rangeStep_iterate (n : ℕ) :
(fun x : ℕ × List ℕ => (x.1+1,x.1 :: x.2))^[n] (0,[]) = (n,(List.range n).reverse) := by
induction n with
| zero => rfl
| succ n ih => rw [Function.iterate_succ_apply',ih]; simp [List.range_succ]
def range : Realizer List.range :=
(((id.pair (zero.pair nil)).comp rangeStep.iterate).comp (snd.comp reverse)).congr (fun n => by
simp only [Function.comp_apply,rangeStep_iterate,List.reverse_reverse,id_eq])
end Realizer
theorem finRange_val (n : ℕ) : (List.finRange n).map Fin.val = List.range n := by
induction n with
| zero => rfl
| succ n ih =>
rw [List.finRange_succ_last,List.map_append,List.map_map]
simpa only [Function.comp_def,Fin.val_castSucc,List.map_cons,List.map_nil,Fin.val_last,ih]
using (List.range_succ (n := n)).symm
namespace Uniform
def makeUniverse : Uniform (fun n (_ : Cardinal n) => (Universe.mk () : Universe n)) where
transform := Realizer.range.transform
charge := Realizer.range.charge
routine := Realizer.range.routine
correct n _ := by
change Realizer.range.transform (enc n) = enc (List.finRange n)
rw [Realizer.range.correct,← finRange_val]
exact enc_list_map Fin.val (fun _ => rfl) _
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
variable {α : Type u4} [Coding α]
theorem volume_append (xs ys : List α) : volume (xs ++ ys)+1 = volume xs+volume ys := by
induction xs with
| nil => simp [Nat.add_comm]
| cons a xs ih => simp only [List.cons_append,volume_cons]; omega
theorem volume_reverse (xs : List α) : volume xs.reverse = volume xs := by
induction xs with
| nil => rfl
| cons a xs ih =>
rw [List.reverse_cons]
have := volume_append xs.reverse [a]
simp only [volume_cons,volume_nil,ih] at this ⊢
omega
namespace Uniform
variable {I : Type u5} {α : I → Type u6} {β : I → Type u7} {γ : I → Type u8}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
variable {f : ∀ i, α i → β i} {g : ∀ i, β i → γ i}
@[simp] theorem time_id (i : I) (x : α i) :
(id : Uniform (fun i (x : α i) => x)).time i x = volume x+2 := rfl
@[simp] theorem time_fst (i : I) (x : α i × β i) :
(fst : Uniform (fun i (x : α i × β i) => x.1)).time i x = volume x+2 := rfl
@[simp] theorem time_snd (i : I) (x : α i × β i) :
(snd : Uniform (fun i (x : α i × β i) => x.2)).time i x = volume x+2 := rfl
@[simp] theorem time_nil (i : I) (x : α i) :
(nil : Uniform (fun i (_ : α i) => ([] : List (β i)))).time i x = 2 := rfl
@[simp] theorem time_unit (i : I) (x : α i) :
(unit : Uniform (fun i (_ : α i) => ())).time i x = 2 := rfl
@[simp] theorem time_zero (i : I) (x : α i) :
(zero : Uniform (fun i (_ : α i) => (0 : ℕ))).time i x = 2 := rfl
@[simp] theorem time_false (i : I) (x : α i) :
(false : Uniform (fun i (_ : α i) => Bool.false)).time i x = 2 := rfl
@[simp] theorem time_congr {f' : ∀ i, α i → β i} (R : Uniform f)
(h : ∀ i x, f i x = f' i x) (i : I) (x : α i) :
(R.congr h).time i x = R.time i x := rfl
@[simp] theorem time_reinterpret (f : ∀ i, α i → β i) (h : ∀ i x, enc (f i x) = enc x)
(i : I) (x : α i) : (reinterpret f h).time i x = volume x+2 := rfl
@[simp] theorem time_cons (i : I) (x : α i × List (α i)) : cons.time i x = volume x+2 := rfl
theorem time_comp (R : Uniform f) (S : Uniform g) (i : I) (x : α i) :
(R.comp S).time i x = R.time i x+S.time i (f i x)+10*(volume (f i x)+1) := by
simp only [comp,time,Routine.comp,R.correct,volume]
theorem time_pair {g : ∀ i, α i → γ i} (R : Uniform f) (S : Uniform g) (i : I) (x : α i) :
(R.pair S).time i x = R.time i x+S.time i x+20*(volume x+volume (f i x)+volume (g i x)+1) := by
simp only [pair,time,Routine.pair,R.correct,S.correct,volume]
theorem time_fold {F : ∀ i, α i × β i → β i} (R : Uniform F) (i : I) (x : List (α i) × β i) :
R.fold.time i x = 2*volume x+6+Realizer.foldTime (R.specialize i) x.2 x.1 :=
(R.specialize i).time_fold x
theorem time_choose {g : ∀ i, α i → β i} (R : Uniform f) (S : Uniform g)
(i : I) (x : Bool × α i) :
(R.choose S).time i x = ((snd (α := fun _ : I => Bool) (β := α)).comp R).time i x+
((snd (α := fun _ : I => Bool) (β := α)).comp S).time i x+
30*(volume x+volume (f i x.2)+volume (g i x.2)+1) :=
(R.specialize i).time_choose (S.specialize i) x
theorem time_constant {δ : Type u9} [Coding δ] (a : δ) (i : I) (x : α i) :
(constant a : Uniform (fun i (_ : α i) => a)).time i x =
(2*volume a+1)*(20*volume x+50*volume a+50) := rfl
theorem time_reverse (i : I) (xs : List (α i)) :
reverse.time i xs ≤ 200*(xs.length+1)*(volume xs+1) := by
have hf : ∀ (xs ys : List (α i)),
Realizer.foldTime ((cons : Uniform (fun i (x : α i × List (α i)) => x.1 :: x.2)).specialize i) ys xs ≤
xs.length * (100*(volume xs+volume ys+1))+1 := by
intro xs; induction xs with
| nil => intro ys; simp only [Realizer.foldTime,List.length_nil,Nat.zero_mul,Nat.zero_add]; rfl
| cons a xs ih =>
intro ys
have hh := ih (a :: ys)
change volume (a,ys)+2+Realizer.foldTime _ (a :: ys) xs+
20*(volume (a :: xs)+volume ys+volume (a :: ys)+1) ≤ _
simp only [volume_pair,volume_cons,List.length_cons] at hh ⊢
nlinarith [volume_pos a,volume_pos xs,volume_pos ys]
simp only [reverse,time_congr,time_comp,time_pair,time_id,time_nil,time_fold,volume_pair,volume_nil]
have hh := hf xs []
simp only [volume_nil] at hh
nlinarith [volume_pos xs]
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
instance {α : Type u10} [Coding α] (n : ℕ) : Coding (Fin n → α) := ⟨fun f => enc (List.ofFn f)⟩
@[simp] theorem enc_function {α : Type u11} [Coding α] {n : ℕ} (f : Fin n → α) :
enc f = enc (List.ofFn f) := rfl
namespace Uniform
variable {I : Type u12} {α : I → Type u13} [∀ i, Coding (α i)]
def tail : Uniform (fun (i : I) (xs : List (α i)) => xs.tail) :=
⟨Data.tail,_,Routine.select Bool.false,fun _ xs => by cases xs <;> rfl⟩
def drop : Uniform (fun (i : I) (x : List (α i) × ℕ) => x.1.drop x.2) :=
(swap.comp tail.iterate).congr (fun i x => by
dsimp only [Function.comp_apply]
have h : ∀ (n : ℕ) (xs : List (α i)), List.tail^[n] xs = xs.drop n := by
intro n; induction n with
| zero => intro xs; rfl
| succ n ih => intro xs; rw [Function.iterate_succ_apply,ih,List.drop_tail]
exact h x.2 x.1)
def getElem? : Uniform (fun (i : I) (x : List (α i) × ℕ) => x.1[x.2]?) :=
(drop.comp head?).congr (fun _ _ => by simp only [Function.comp_apply,List.head?_drop])
def getElemD : Uniform (fun (i : I) (x : (List (α i) × ℕ) × α i) => x.1.1.getD x.1.2 x.2) :=
(getElem?.onFst.comp getD).congr (fun _ _ => List.getD_eq_getElem?_getD.symm)
end Uniform
namespace Uniform
variable {α : ℕ → Type u14} {β : ℕ → Type u15} [∀ n, Coding (α n)] [∀ n, Coding (β n)]
def functionList : Uniform (fun n (f : Fin n → α n) => List.ofFn f) :=
reinterpret _ (fun _ _ => rfl)
def functionGetOption : Uniform (fun n (x : (Fin n → α n) × Fin n) => Option.some (x.1 x.2)) :=
(((fst.comp functionList).pair (snd.comp finVal)).comp getElem?).congr (fun _ x => by
simp only [Function.comp_apply,List.getElem?_ofFn,dite_eq_left x.2.isLt])
def functionGet : Uniform (fun n (x : (Fin n → α n) × Fin n) => x.1 x.2) where
transform := Data.head ∘ (functionGetOption (α := α)).transform
charge := _
routine := (functionGetOption (α := α)).routine.comp (Routine.select true)
correct n x := by
simp only [Function.comp_apply,(functionGetOption (α := α)).correct,enc_some,Data.head]
def vectorMap {f : ∀ n, Fin n × α n → β n} (R : Uniform f) :
Uniform (fun n (x : Universe n × α n) => fun v => f n (v,x.2)) where
transform := (universeList.onFst.comp R.map).transform
charge := (universeList.onFst.comp R.map).charge
routine := (universeList.onFst.comp R.map).routine
correct n x := by
rw [(universeList.onFst.comp R.map).correct]
simp only [Function.comp_apply,enc_function,List.ofFn_eq_map]
end Uniform
end ThreeMachine.StackCompiler
end
end OAI
end
section
-- module ListRoutines
namespace OAI
universe u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16 u17 u18
section
namespace ThreeMachine.StackCompiler.Uniform
variable {I : Type u1} {α : I → Type u2} {β : I → Type u3} {γ : I → Type u4}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
variable {f : ∀ i, α i × γ i → β i}
theorem time_mapBody (R : Uniform f) (i : I) (a : α i) (e : γ i) (ys : List (β i)) :
(mapBody R).time i (a,(e,ys)) ≤ R.time i (a,e)+
1000*(volume a+volume e+volume ys+volume (f i (a,e))+1) := by
simp only [mapBody,time_pair,time_comp,time_fst,time_snd,time_cons,volume_pair,volume_cons,Function.comp_apply]
omega
theorem foldTime_mapBody (R : Uniform f) (i : I) (e : γ i) (T : ℕ)
(xs : List (α i)) (ys : List (β i))
(hT : ∀ a ∈ xs, R.time i (a,e) ≤ T) :
Realizer.foldTime ((mapBody R).specialize i) (e,ys) xs ≤
xs.length*(T+4000*(volume xs+volume e+volume (xs.map (fun a => f i (a,e)))+volume ys+1))+1 := by
induction xs generalizing ys with
| nil => simp only [Realizer.foldTime,List.length_nil,Nat.zero_mul,Nat.zero_add]; rfl
| cons a xs ih =>
have hta := hT a (by simp)
have ht := ih (f i (a,e) :: ys) (fun a ha => hT a (by simp [ha]))
have hb := time_mapBody R i a e ys
simp only [Realizer.foldTime]
change (mapBody R).time i (a,(e,ys))+
Realizer.foldTime ((mapBody R).specialize i) (e,f i (a,e) :: ys) xs+
20*(volume (a :: xs)+volume (e,ys)+volume (e,f i (a,e) :: ys)+1) ≤ _
simp only [volume_pair,volume_cons,List.length_cons,List.map_cons] at ht hb ⊢
nlinarith [volume_pos a,volume_pos e,volume_pos ys,volume_pos xs,volume_pos (f i (a,e))]
theorem time_map (R : Uniform f) (i : I) (xs : List (α i)) (e : γ i) (T : ℕ)
(hT : ∀ a ∈ xs, R.time i (a,e) ≤ T) :
R.map.time i (xs,e) ≤
30000*(xs.length+1)*(T+volume xs+volume e+volume (xs.map (fun a => f i (a,e)))+1) := by
have hf := foldTime_mapBody R i e T xs [] hT
have hr := time_reverse i ((xs.map (fun a => f i (a,e))).reverse)
simp only [volume_nil] at hf
simp only [List.length_reverse,List.length_map,volume_reverse] at hr
simp only [map,time_congr,time_comp,time_pair,time_fst,time_snd,time_nil,time_fold,
Function.comp_apply,Realizer.map_fold_eq,List.append_nil,volume_pair,volume_nil,volume_reverse]
nlinarith [volume_pos xs,volume_pos e,volume_pos (xs.map (fun a => f i (a,e)))]
end ThreeMachine.StackCompiler.Uniform
namespace ThreeMachine.StackCompiler
def lookupList {K : Type u5} {V : Type u6} [DecidableEq K] : List (K × V) → K → Option V
| [], _ => none
| (a,b) :: xs, k => if a = k then some b else lookupList xs k
namespace Uniform
variable {I : Type u7} {α : I → Type u8} {β : I → Type u9} {γ : I → Type u10}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
def mapList {f : ∀ i, α i → β i} (R : Uniform f) :
Uniform (fun i (xs : List (α i)) => xs.map (f i)) :=
((id.pair unit).comp (fst.comp R).map).congr (fun _ _ => rfl)
def mapOption {f : ∀ i, α i → β i} (R : Uniform f) :
Uniform (fun i (x : Option (α i)) => x.map (f i)) :=
((id.pair unit).comp (fst.comp R).optionMap).congr (fun _ _ => rfl)
def optionOrElse : Uniform (fun (i : I) (x : Option (α i) × Option (α i)) => x.1.or x.2) :=
(fst.comp optionIsSome).ite fst snd |>.congr (fun _ x => by
rcases x with ⟨o,e⟩; cases o <;> rfl)
def lookup [∀ i, DecidableEq (α i)]
(E : Uniform (fun i (x : α i × α i) => decide (x.1 = x.2))) :
Uniform (fun i (x : List (α i × β i) × α i) => lookupList x.1 x.2) :=
((((fst.comp fst).pair snd).comp E).find?.comp snd.mapOption).congr (fun i x => by
dsimp only [Function.comp_apply]
induction x.1 with
| nil => rfl
| cons a xs ih =>
by_cases ha : a.1 = x.2 <;> simp [lookupList,ha,ih])
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Uniform
variable {I : Type u11} {J : Type u12} {α : I → Type u13} {β : I → Type u14} {γ : I → Type u15}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
variable {f : ∀ i, α i → β i}
def reindex (R : Uniform f) (φ : J → I) : Uniform (fun j => f (φ j)) where
transform := R.transform
charge := R.charge
routine := R.routine
correct j x := R.correct (φ j) x
def finValue (d : I → ℕ) : Uniform (fun i (x : Fin (d i)) => x.val) :=
reinterpret _ (fun _ _ => rfl)
def cardinalValue (d : I → ℕ) : Uniform (fun i (_ : Cardinal (d i)) => d i) :=
reinterpret _ (fun _ _ => rfl)
def universeListAny (d : I → ℕ) : Uniform (fun i (_ : Universe (d i)) => List.finRange (d i)) :=
reinterpret _ (fun _ _ => rfl)
def makeUniverseAny (d : I → ℕ) : Uniform (fun i (_ : Cardinal (d i)) => (Universe.mk () : Universe (d i))) :=
makeUniverse.reindex d
def functionListAny (d : I → ℕ) : Uniform (fun i (f : Fin (d i) → α i) => List.ofFn f) :=
reinterpret _ (fun _ _ => rfl)
def functionGetOptionAny (d : I → ℕ) :
Uniform (fun i (x : (Fin (d i) → α i) × Fin (d i)) => Option.some (x.1 x.2)) :=
(((fst.comp (functionListAny d)).pair (snd.comp (finValue d))).comp getElem?).congr (fun _ x => by
simp only [Function.comp_apply,List.getElem?_ofFn,dite_eq_left x.2.isLt])
def functionGetAny (d : I → ℕ) : Uniform (fun i (x : (Fin (d i) → α i) × Fin (d i)) => x.1 x.2) where
transform := Data.head ∘ (functionGetOptionAny (α := α) d).transform
charge := _
routine := (functionGetOptionAny (α := α) d).routine.comp (Routine.select true)
correct i x := by
simp only [Function.comp_apply,(functionGetOptionAny (α := α) d).correct,enc_some,Data.head]
def vectorMapAny (d : I → ℕ) {f : ∀ i, Fin (d i) × α i → β i} (R : Uniform f) :
Uniform (fun i (x : Universe (d i) × α i) => fun v => f i (v,x.2)) where
transform := ((universeListAny d).onFst.comp R.map).transform
charge := ((universeListAny d).onFst.comp R.map).charge
routine := ((universeListAny d).onFst.comp R.map).routine
correct i x := by
rw [((universeListAny d).onFst.comp R.map).correct]
simp only [Function.comp_apply,enc_function,List.ofFn_eq_map]
def recode {H : Type u16} {δ : H → Type u17} {ε : H → Type u18} [∀ h, Coding (δ h)] [∀ h, Coding (ε h)]
{g : ∀ h, δ h → ε h} (R : Uniform g) (f : ∀ i, α i → β i)
(h : ∀ i x, ∃ j y, enc y = enc x ∧ enc (g j y) = enc (f i x)) : Uniform f where
transform := R.transform
charge := R.charge
routine := R.routine
correct i x := by
obtain ⟨j,y,hin,hout⟩ := h i x
rw [← hin,R.correct,hout]
def cardinalMap (d : I → ℕ) {g : ℕ → ℕ} (R : Realizer g) :
Uniform (fun i (_ : Cardinal (d i)) => (Cardinal.mk () : Cardinal (g (d i)))) where
transform := R.transform
charge := R.charge
routine := R.routine
correct i _ := R.correct (d i)
end ThreeMachine.StackCompiler.Uniform
end
end OAI
end
section
-- module ProgramRoutines
namespace OAI
universe u1 u2 u3 u4 u5 u6 u7 u8
section
namespace ThreeMachine.StackCompiler
open ThreeMachine.Algorithm
instance (n : ℕ) : Coding (Algorithm.State (Fin n)) :=
⟨fun s => enc (s.left,(s.middle,s.right))⟩
instance (n : ℕ) : Coding (Algorithm.Block (Fin n)) :=
⟨fun s => enc (s.length,s.time)⟩
abbrev Matrix (n : ℕ) := Fin n → Fin n → Bool
def matrixRel {n : ℕ} (M : Matrix n) (x y : Fin n) : Prop := M x y = true
instance {n : ℕ} (M : Matrix n) : DecidableRel (matrixRel M) :=
fun _ _ => inferInstanceAs (Decidable (_ = true))
namespace Uniform
def universeNumber : Uniform (fun n (_ : Universe n) => n) :=
(universeList.comp length).congr (fun _ _ => List.length_finRange)
def stateParts : Uniform (fun n (s : Algorithm.State (Fin n)) => (s.left,(s.middle,s.right))) :=
reinterpret _ (fun _ _ => rfl)
def stateMake : Uniform (fun n (x : Finset (Fin n) × (Finset (Fin n) × Finset (Fin n))) =>
(⟨x.1,x.2.1,x.2.2⟩ : Algorithm.State (Fin n))) :=
reinterpret _ (fun _ _ => rfl)
def stateLeft : Uniform (fun n (s : Algorithm.State (Fin n)) => s.left) := stateParts.comp fst
def stateMiddle : Uniform (fun n (s : Algorithm.State (Fin n)) => s.middle) := stateParts.comp (snd.comp fst)
def stateRight : Uniform (fun n (s : Algorithm.State (Fin n)) => s.right) := stateParts.comp (snd.comp snd)
def stateEq : Uniform (fun n (x : Algorithm.State (Fin n) × Algorithm.State (Fin n)) =>
decide (x.1 = x.2)) :=
(((((fst.comp stateLeft).pair (snd.comp stateLeft)).comp setEq).pair
(((((fst.comp stateMiddle).pair (snd.comp stateMiddle)).comp setEq).pair
(((fst.comp stateRight).pair (snd.comp stateRight)).comp setEq)).comp (Realizer.and.uniform ℕ))).comp
(Realizer.and.uniform ℕ)).congr (fun _ x => by
rcases x with ⟨⟨a,b,c⟩,⟨d,e,f⟩⟩
apply Bool.eq_iff_iff.mpr
simp)
def blockParts : Uniform (fun n (s : Algorithm.Block (Fin n)) => (s.length,s.time)) :=
reinterpret _ (fun _ _ => rfl)
def blockMake : Uniform (fun n (x : ℕ × (Fin n → ℕ)) => (⟨x.1,x.2⟩ : Algorithm.Block (Fin n))) :=
reinterpret _ (fun _ _ => rfl)
def blockLength : Uniform (fun n (s : Algorithm.Block (Fin n)) => s.length) := blockParts.comp fst
def blockTime : Uniform (fun n (s : Algorithm.Block (Fin n)) => s.time) := blockParts.comp snd
def matrixGet : Uniform (fun n (x : Matrix n × (Fin n × Fin n)) => x.1 x.2.1 x.2.2) :=
((((fst.pair (snd.comp fst)).comp functionGet).pair (snd.comp snd)).comp functionGet)
def setAll {γ : ℕ → Type u1} [∀ n, Coding (γ n)]
{p : ∀ n, Fin n × γ n → Bool} (P : Uniform p) :
Uniform (fun n (x : Finset (Fin n) × γ n) => decide (∀ a ∈ x.1, p n (a,x.2) = true)) :=
(setList.onFst.comp P.all).congr (fun _ x => by
apply Bool.eq_iff_iff.mpr
simp only [Function.comp_apply,List.all_eq_true,Finset.mem_sort,decide_eq_true_eq])
def setAny {γ : ℕ → Type u2} [∀ n, Coding (γ n)]
{p : ∀ n, Fin n × γ n → Bool} (P : Uniform p) :
Uniform (fun n (x : Finset (Fin n) × γ n) => decide (∃ a ∈ x.1, p n (a,x.2) = true)) :=
(setList.onFst.comp P.any).congr (fun _ x => by
apply Bool.eq_iff_iff.mpr
simp only [Function.comp_apply,List.any_eq_true,Finset.mem_sort,decide_eq_true_eq])
variable {I : Type u3} {α : I → Type u4} [∀ i, Coding (α i)]
def andD {p q : ∀ i, α i → Prop} [∀ i, DecidablePred (p i)] [∀ i, DecidablePred (q i)]
(P : Uniform (fun i x => decide (p i x))) (Q : Uniform (fun i x => decide (q i x))) :
Uniform (fun i x => decide (p i x ∧ q i x)) :=
((P.pair Q).comp (Realizer.and.uniform I)).congr (fun _ _ => by simp)
def orD {p q : ∀ i, α i → Prop} [∀ i, DecidablePred (p i)] [∀ i, DecidablePred (q i)]
(P : Uniform (fun i x => decide (p i x))) (Q : Uniform (fun i x => decide (q i x))) :
Uniform (fun i x => decide (p i x ∨ q i x)) :=
((P.pair Q).comp (Realizer.or.uniform I)).congr (fun _ _ => by simp)
def noEdges : Uniform (fun n (x : Matrix n × (Finset (Fin n) × Finset (Fin n))) =>
decide (∀ a ∈ x.2.1, ∀ b ∈ x.2.2, ¬matrixRel x.1 a b)) := by
let E : Uniform (fun n (x : Fin n × (Matrix n × Fin n)) => !x.2.1 x.2.2 x.1) :=
(((snd.comp fst).pair ((snd.comp snd).pair fst)).comp matrixGet).comp (Realizer.not.uniform ℕ)
let F : Uniform (fun n (x : Fin n × (Matrix n × Finset (Fin n))) =>
decide (∀ b ∈ x.2.2, ¬matrixRel x.2.1 x.1 b)) :=
(((snd.comp snd).pair ((snd.comp fst).pair fst)).comp E.setAll).congr (fun _ _ => by
simp only [Function.comp_apply,Bool.not_eq_true,matrixRel,Bool.not_eq_true'])
exact (((snd.comp fst).pair (fst.pair (snd.comp snd))).comp F.setAll).congr (fun _ _ => by
simp only [Function.comp_apply,decide_eq_true_eq])
def stateCandidate : Uniform (fun n (x : Universe n ×
(Finset (Fin n) × (Finset (Fin n) × Finset (Fin n)))) =>
Algorithm.State.candidate x.2.1 x.2.2.1 x.2.2.2) := by
let L := (((snd.comp fst).pair (snd.comp (snd.comp fst))).comp setInter :
Uniform (fun n (x : Universe n × (Finset (Fin n) × (Finset (Fin n) × Finset (Fin n)))) => x.2.1 ∩ x.2.2.1))
let Z := (snd.comp (snd.comp snd) :
Uniform (fun n (x : Universe n × (Finset (Fin n) × (Finset (Fin n) × Finset (Fin n)))) => x.2.2.2))
exact (L.pair (Z.pair (((snd.comp fst).pair ((fst.pair (L.pair Z)).comp setUnion)).comp setDiff))).comp stateMake
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
open ThreeMachine.Algorithm
namespace Uniform
def stateUpto : Uniform (fun n (x : Universe n × Algorithm.State (Fin n)) => x.2.upto) :=
(fst.pair ((snd.comp stateLeft).pair (snd.comp stateMiddle))).comp setUnion
abbrev CompatInput (n : ℕ) := Universe n × (Matrix n × (Finset (Fin n) × Algorithm.State (Fin n)))
def scU : Uniform (fun n (x : CompatInput n) => x.1) := fst
def scM : Uniform (fun n (x : CompatInput n) => x.2.1) := snd.comp fst
def scW : Uniform (fun n (x : CompatInput n) => x.2.2.1) := snd.comp (snd.comp fst)
def scS : Uniform (fun n (x : CompatInput n) => x.2.2.2) := snd.comp (snd.comp snd)
def scL := scS.comp stateLeft
def scZ := scS.comp stateMiddle
def scR := scS.comp stateRight
def scLZ := (scU.pair (scL.pair scZ)).comp setUnion
def scLZR := (scU.pair (scLZ.pair scR)).comp setUnion
def scA := (scLZR.pair scW).comp setEq
def scB := (scL.pair scZ).comp setDisjoint
def scC := (scL.pair scR).comp setDisjoint
def scD := (scZ.pair scR).comp setDisjoint
def scE := ((scZ.comp setCard).pair (constant 3)).comp (Realizer.eqNat.uniform ℕ)
def scF := (scM.pair (scZ.pair scZ)).comp noEdges
def scH := (scM.pair (scZ.pair scL)).comp noEdges
def scI := (scM.pair (scR.pair scL)).comp noEdges
def scJ := (scM.pair (scR.pair scZ)).comp noEdges
def scIJ := scI.andD scJ
def scHIJ := scH.andD scIJ
def scFHIJ := scF.andD scHIJ
def scEFHIJ := scE.andD scFHIJ
def scDEFHIJ := scD.andD scEFHIJ
def scCDEFHIJ := scC.andD scDEFHIJ
def scBCDEFHIJ := scB.andD scCDEFHIJ
def scAll := scA.andD scBCDEFHIJ
def stateCompatible : Uniform (fun n (x : Universe n ×
(Matrix n × (Finset (Fin n) × Algorithm.State (Fin n)))) =>
decide (x.2.2.2.Compatible (matrixRel x.2.1) x.2.2.1)) :=
scAll.congr (fun _ _ => by apply decide_eq_decide.mpr; rfl)
def blockEmpty : Uniform (fun n (_ : Universe n) => (Algorithm.Block.empty : Algorithm.Block (Fin n))) :=
(zero.pair ((id.pair unit).comp zero.vectorMap)).comp blockMake
def blockTriple : Uniform (fun n (_ : Universe n) => (Algorithm.Block.triple : Algorithm.Block (Fin n))) :=
((constant 1).pair ((id.pair unit).comp (constant 1).vectorMap)).comp blockMake
def blockAppend : Uniform (fun n (x : Universe n ×
(Finset (Fin n) × (Algorithm.Block (Fin n) × Algorithm.Block (Fin n)))) =>
Algorithm.Block.append x.2.1 x.2.2.1 x.2.2.2) := by
let F : Uniform (fun n (x : Fin n ×
(Finset (Fin n) × (Algorithm.Block (Fin n) × Algorithm.Block (Fin n)))) =>
if x.1 ∈ x.2.1 then x.2.2.1.time x.1 else x.2.2.1.length+x.2.2.2.time x.1) := by
let S := (snd.comp (snd.comp fst) : Uniform (fun n (x : Fin n ×
(Finset (Fin n) × (Algorithm.Block (Fin n) × Algorithm.Block (Fin n)))) => x.2.2.1))
let T := (snd.comp (snd.comp snd) : Uniform (fun n (x : Fin n ×
(Finset (Fin n) × (Algorithm.Block (Fin n) × Algorithm.Block (Fin n)))) => x.2.2.2))
exact (((fst.pair (snd.comp fst)).comp setMem).ite
(((S.comp blockTime).pair fst).comp functionGet)
(((S.comp blockLength).pair (((T.comp blockTime).pair fst).comp functionGet)).comp
(Realizer.add.uniform ℕ))).congr (fun _ _ => by simp)
exact ((((snd.comp (snd.comp fst)).comp blockLength).pair
((snd.comp (snd.comp snd)).comp blockLength)).comp (Realizer.add.uniform ℕ)).pair
F.vectorMap |>.comp blockMake
def stateAdvance : Uniform (fun n (x : Universe n ×
(Algorithm.State (Fin n) × (Algorithm.Block (Fin n) × Algorithm.Block (Fin n)))) =>
x.2.1.advance x.2.2.1 x.2.2.2) := by
let U := (fst : Uniform (fun n (x : Universe n ×
(Algorithm.State (Fin n) × (Algorithm.Block (Fin n) × Algorithm.Block (Fin n)))) => x.1))
let V := (snd.comp fst : Uniform (fun n (x : Universe n ×
(Algorithm.State (Fin n) × (Algorithm.Block (Fin n) × Algorithm.Block (Fin n)))) => x.2.1))
let S := (snd.comp (snd.comp fst) : Uniform (fun n (x : Universe n ×
(Algorithm.State (Fin n) × (Algorithm.Block (Fin n) × Algorithm.Block (Fin n)))) => x.2.2.1))
let T := (snd.comp (snd.comp snd) : Uniform (fun n (x : Universe n ×
(Algorithm.State (Fin n) × (Algorithm.Block (Fin n) × Algorithm.Block (Fin n)))) => x.2.2.2))
let B := (U.pair ((V.comp stateLeft).pair (S.pair (U.comp blockTriple)))).comp blockAppend
exact (U.pair (((U.pair V).comp stateUpto).pair (B.pair T))).comp blockAppend
variable {I : Type u5} {α β γ : I → Type}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
def lookupA [∀ i, DecidableEq (α i)]
(E : Uniform (fun i (x : α i × α i) => decide (x.1 = x.2))) :
Uniform (fun i (x : List (α i × β i) × α i) => Algorithm.lookup x.1 x.2) :=
(lookup E).congr (fun _ x => by
induction x.1 with
| nil => rfl
| cons a xs ih => simp only [lookupList,Algorithm.lookup]; split <;> simp_all)
def firstResultA {f : ∀ i, α i × γ i → Option (β i)} (R : Uniform f) :
Uniform (fun i (x : List (α i) × γ i) => Algorithm.firstResult (fun a => f i (a,x.2)) x.1) :=
R.firstResult.congr (fun _ x => by
induction x.1 with
| nil => rfl
| cons a xs ih => simp only [List.filterMap_cons,Algorithm.firstResult]; cases f _ (a,x.2) <;> simp_all)
def tableOfA {f : ∀ i, α i × γ i → Option (β i)} (R : Uniform f) :
Uniform (fun i (x : List (α i) × γ i) => Algorithm.tableOf x.1 (fun a => f i (a,x.2))) :=
R.tableOf
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
open ThreeMachine.Algorithm
abbrev Table (n : ℕ) := List (Finset (Fin n) × Algorithm.Block (Fin n))
abbrev Marks (n : ℕ) := List (Algorithm.State (Fin n) × Algorithm.Block (Fin n))
namespace Uniform
variable {I : Type u6} {α : I → Type u7} {β : I → Type u8}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)]
def singleton : Uniform (fun i (a : α i) => [a]) := (id.pair nil).comp cons
def product : Uniform (fun i (x : List (α i) × List (β i)) => x.1.product x.2) :=
((snd.pair fst).comp swap.map).flatMap.congr (fun _ _ => rfl)
def states : Uniform (fun n (x : Universe n × (Matrix n ×
(List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n))))) =>
Algorithm.states (matrixRel x.2.1) x.2.2.1 x.2.2.2.1 x.2.2.2.2) := by
let C : Uniform (fun n (x : (Finset (Fin n) × Finset (Fin n)) ×
(Universe n × Finset (Fin n))) => Algorithm.State.candidate x.2.2 x.1.1 x.1.2) :=
((snd.comp fst).pair ((snd.comp snd).pair ((fst.comp fst).pair (fst.comp snd)))).comp stateCandidate
let F := (snd.comp (snd.comp fst) : Uniform (fun n (x : Universe n × (Matrix n ×
(List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n))))) => x.2.2.1))
let Z := (snd.comp (snd.comp (snd.comp fst)) : Uniform (fun n (x : Universe n × (Matrix n ×
(List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n))))) => x.2.2.2.1))
let W := (snd.comp (snd.comp (snd.comp snd)) : Uniform (fun n (x : Universe n × (Matrix n ×
(List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n))))) => x.2.2.2.2))
let S := (((F.pair Z).comp product).pair (fst.pair W)).comp C.map
let P : Uniform (fun n (x : Algorithm.State (Fin n) ×
(Universe n × (Matrix n × Finset (Fin n)))) =>
decide (x.1.Compatible (matrixRel x.2.2.1) x.2.2.2)) :=
((snd.comp fst).pair ((snd.comp (snd.comp fst)).pair ((snd.comp (snd.comp snd)).pair fst))).comp stateCompatible
exact ((S.pair (fst.pair ((snd.comp fst).pair W))).comp P.filter).congr (fun _ x => by
simp only [Function.comp_apply,Algorithm.states,List.product,List.map_flatMap,List.map_map]
rfl)
def advanceLast : Uniform (fun n (x : Algorithm.Block (Fin n) ×
(Universe n × (Algorithm.State (Fin n) × Algorithm.Block (Fin n)))) =>
x.2.2.1.advance x.2.2.2 x.1) :=
((snd.comp fst).pair ((snd.comp (snd.comp fst)).pair ((snd.comp (snd.comp snd)).pair fst))).comp stateAdvance
def tryAdvance : Uniform (fun n (x : Universe n ×
(Table n × ((Algorithm.State (Fin n) × Algorithm.Block (Fin n)) × Algorithm.State (Fin n)))) =>
Algorithm.tryAdvance x.2.1 x.2.2.1 x.2.2.2) := by
let U := (fst : Uniform (fun n (x : Universe n ×
(Table n × ((Algorithm.State (Fin n) × Algorithm.Block (Fin n)) × Algorithm.State (Fin n)))) => x.1))
let T := (snd.comp fst : Uniform (fun n (x : Universe n ×
(Table n × ((Algorithm.State (Fin n) × Algorithm.Block (Fin n)) × Algorithm.State (Fin n)))) => x.2.1))
let A := (snd.comp (snd.comp fst) : Uniform (fun n (x : Universe n ×
(Table n × ((Algorithm.State (Fin n) × Algorithm.Block (Fin n)) × Algorithm.State (Fin n)))) => x.2.2.1))
let V := (snd.comp (snd.comp snd) : Uniform (fun n (x : Universe n ×
(Table n × ((Algorithm.State (Fin n) × Algorithm.Block (Fin n)) × Algorithm.State (Fin n)))) => x.2.2.2))
let W := (U.pair (A.comp fst)).comp stateUpto
let L := V.comp stateLeft
let P := (W.pair L).comp setSubset
let O := (T.pair ((L.pair W).comp setDiff)).comp (lookupA setEq)
exact (P.ite ((O.pair (U.pair A)).comp advanceLast.optionMap) none).congr (fun _ _ => by
simp only [Function.comp_apply,Algorithm.tryAdvance,decide_eq_true_eq])
def expandBody : Uniform (fun n (x : Algorithm.State (Fin n) ×
(Universe n × (Table n × Marks n))) =>
match Algorithm.lookup x.2.2.2 x.1 with
| Option.some s => Option.some s
| Option.none => Algorithm.firstResult (fun u => Algorithm.tryAdvance x.2.2.1 u x.1) x.2.2.2) := by
let A : Uniform (fun n (x : (Algorithm.State (Fin n) × Algorithm.Block (Fin n)) ×
(Universe n × (Table n × Algorithm.State (Fin n)))) =>
Algorithm.tryAdvance x.2.2.1 x.1 x.2.2.2) :=
((snd.comp fst).pair ((snd.comp (snd.comp fst)).pair (fst.pair (snd.comp (snd.comp snd))))).comp tryAdvance
let O := (((snd.comp (snd.comp snd)).pair fst).comp (lookupA stateEq) :
Uniform (fun n (x : Algorithm.State (Fin n) × (Universe n × (Table n × Marks n))) =>
Algorithm.lookup x.2.2.2 x.1))
let B := ((snd.comp (snd.comp snd)).pair
((snd.comp fst).pair ((snd.comp (snd.comp fst)).pair fst))).comp A.firstResultA
exact ((O.pair B).comp optionOrElse).congr (fun _ x => by
simp only [Function.comp_apply]; cases Algorithm.lookup x.2.2.2 x.1 <;> rfl)
def expand : Uniform (fun n (x : Universe n ×
(Table n × (List (Algorithm.State (Fin n)) × Marks n))) =>
Algorithm.expand x.2.1 x.2.2.1 x.2.2.2) :=
((snd.comp (snd.comp fst)).pair
(fst.pair ((snd.comp fst).pair (snd.comp (snd.comp snd))))).comp expandBody.tableOfA |>.congr
(fun _ x => by
simp only [Function.comp_apply,Algorithm.expand]
congr 1
funext v
cases Algorithm.lookup x.2.2.2 v <;> rfl)
def initialMarks : Uniform (fun n (x : Table n × List (Algorithm.State (Fin n))) =>
Algorithm.tableOf x.2 (fun v => Algorithm.lookup x.1 v.left)) :=
(swap.comp ((snd.pair (fst.comp stateLeft)).comp (lookupA setEq)).tableOfA)
def markings : Uniform (fun n (x : ℕ ×
(Universe n × (Table n × List (Algorithm.State (Fin n))))) =>
Algorithm.markings x.2.2.1 x.2.2.2 x.1) := by
let F : Uniform (fun n (x : (Universe n × (Table n × List (Algorithm.State (Fin n)))) × Marks n) =>
(x.1,Algorithm.expand x.1.2.1 x.1.2.2 x.2)) :=
fst.pair ((((fst.comp fst).pair ((fst.comp (snd.comp fst)).pair
((fst.comp (snd.comp snd)).pair snd)))).comp expand)
exact (((fst.pair (snd.pair (snd.comp (snd.comp initialMarks)))).comp F.iterate).comp snd).congr
(fun n x => by
dsimp only [Function.comp_apply]
have h : ∀ k, (fun p => (p.1,Algorithm.expand p.1.2.1 p.1.2.2 p.2))^[k]
(x.2,Algorithm.tableOf x.2.2.2 (fun v => Algorithm.lookup x.2.2.1 v.left)) =
(x.2,Algorithm.markings x.2.2.1 x.2.2.2 k) := by
intro k; induction k with
| zero => rfl
| succ k ih => rw [Function.iterate_succ_apply',ih]; rfl
rw [h])
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
open ThreeMachine.Algorithm
namespace Uniform
def finishing : Uniform (fun n (x : (Algorithm.State (Fin n) × Algorithm.Block (Fin n)) ×
(Universe n × Table n)) =>
(Algorithm.lookup x.2.2 x.1.1.right).map (x.1.1.finish x.1.2)) :=
((((snd.comp snd).pair ((fst.comp fst).comp stateRight)).comp (lookupA setEq)).pair
((snd.comp fst).pair fst)).comp advanceLast.optionMap
def solve : Uniform (fun n (x : Universe n × (Matrix n ×
(Table n × (List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n)))))) =>
Algorithm.solve (matrixRel x.2.1) x.2.2.1 x.2.2.2.1 x.2.2.2.2.1 x.2.2.2.2.2) := by
let U := (fst : Uniform (fun n (x : Universe n × (Matrix n ×
(Table n × (List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n)))))) => x.1))
let M := (snd.comp fst : Uniform (fun n (x : Universe n × (Matrix n ×
(Table n × (List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n)))))) => x.2.1))
let T := (snd.comp (snd.comp fst) : Uniform (fun n (x : Universe n × (Matrix n ×
(Table n × (List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n)))))) => x.2.2.1))
let F := (snd.comp (snd.comp (snd.comp fst)) : Uniform (fun n (x : Universe n × (Matrix n ×
(Table n × (List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n)))))) => x.2.2.2.1))
let Z := (snd.comp (snd.comp (snd.comp (snd.comp fst))) : Uniform (fun n (x : Universe n × (Matrix n ×
(Table n × (List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n)))))) => x.2.2.2.2.1))
let W := (snd.comp (snd.comp (snd.comp (snd.comp snd))) : Uniform (fun n (x : Universe n × (Matrix n ×
(Table n × (List (Finset (Fin n)) × (List (Finset (Fin n)) × Finset (Fin n)))))) => x.2.2.2.2.2))
let S := (U.pair (M.pair (F.pair (Z.pair W)))).comp states
let Marks := ((U.comp universeNumber).pair (U.pair (T.pair S))).comp markings
let Out := (Marks.pair (U.pair T)).comp finishing.firstResultA
exact ((W.comp setIsEmpty).ite (U.comp (blockEmpty.comp some)) Out).congr (fun _ _ => by
simp only [Function.comp_apply,Algorithm.solve,decide_eq_true_eq,Fintype.card_fin])
def initialTable : Uniform (fun n (_ : Universe n) => ([(∅,Algorithm.Block.empty)] : Table n)) :=
(setEmpty.pair blockEmpty).comp singleton
def layerStep : Uniform (fun n (x : (Universe n × (Matrix n ×
(List (Finset (Fin n)) × List (Finset (Fin n))))) × Table n) =>
(x.1,Algorithm.tableOf x.1.2.2.1
(Algorithm.solve (matrixRel x.1.2.1) x.2 x.1.2.2.1 x.1.2.2.2))) := by
let B : Uniform (fun n (x : Finset (Fin n) ×
((Universe n × (Matrix n × (List (Finset (Fin n)) × List (Finset (Fin n))))) × Table n)) =>
Algorithm.solve (matrixRel x.2.1.2.1) x.2.2 x.2.1.2.2.1 x.2.1.2.2.2 x.1) :=
((snd.comp (fst.comp fst)).pair ((snd.comp (fst.comp (snd.comp fst))).pair
((snd.comp snd).pair ((snd.comp (fst.comp (snd.comp (snd.comp fst)))).pair
((snd.comp (fst.comp (snd.comp (snd.comp snd)))).pair fst))))).comp solve
exact fst.pair (((fst.comp (snd.comp (snd.comp fst))).pair id).comp B.tableOfA)
def layers : Uniform (fun n (x : ℕ × (Universe n × (Matrix n ×
(List (Finset (Fin n)) × List (Finset (Fin n)))))) =>
Algorithm.layers (matrixRel x.2.2.1) x.2.2.2.1 x.2.2.2.2 x.1) :=
(((fst.pair (snd.pair ((snd.comp fst).comp initialTable))).comp layerStep.iterate).comp snd).congr
(fun n x => by
dsimp only [Function.comp_apply]
have h : ∀ k, (fun p => (p.1,Algorithm.tableOf p.1.2.2.1
(Algorithm.solve (matrixRel p.1.2.1) p.2 p.1.2.2.1 p.1.2.2.2)))^[k]
(x.2,[(∅,Algorithm.Block.empty)]) =
(x.2,Algorithm.layers (matrixRel x.2.2.1) x.2.2.2.1 x.2.2.2.2 k) := by
intro k; induction k with
| zero => rfl
| succ k ih => rw [Function.iterate_succ_apply',ih]; rfl
rw [h])
end Uniform
end ThreeMachine.StackCompiler
end
end OAI
end
section
-- module FamilyRoutines
namespace OAI
universe u1 u2
section
namespace ThreeMachine.StackCompiler
open ThreeMachine.Structure ThreeMachine.Algorithm
namespace Uniform
variable {I : Type u1} {α : I → Type} [∀ i, Coding (α i)]
def natLT : Uniform (fun (_ : I) (x : ℕ × ℕ) => decide (x.1 < x.2)) :=
(swap.comp ((Realizer.le.uniform I).comp (Realizer.not.uniform I))).congr (fun _ x => by
by_cases h : x.1 < x.2
· have hn : ¬ x.2 ≤ x.1 := by omega
simp [Function.comp_apply,h,hn]
· have hn : x.2 ≤ x.1 := by omega
simp [Function.comp_apply,h,hn])
def finCons (k : ℕ) : Uniform (fun i (x : α i × (Fin k → α i)) => (Fin.cons x.1 x.2 : Fin (k+1) → α i)) :=
reinterpret _ (fun _ _ => by simp only [enc_function,List.ofFn_cons]; rfl)
def finEmpty : Uniform (fun i (_ : List (α i)) => (Fin.elim0 : Fin 0 → α i)) where
transform := fun _ => .nil
charge := _
routine := Routine.nil
correct _ _ := by simp only [enc_function,List.ofFn_zero]; rfl
def assignments : (k : ℕ) → Uniform (fun i (xs : List (α i)) => Structure.assignments xs k)
| 0 => finEmpty.comp singleton
| k+1 =>
((id.pair (assignments k)).comp ((snd.pair fst).comp (swap.comp (finCons k)).map).flatMap).congr
(fun _ _ => rfl)
def tripleSet : Uniform (fun n (x : Universe n × (Fin n × (Fin n × Fin n))) =>
({x.2.1,x.2.2.1,x.2.2.2} : Finset (Fin n))) := by
let P : Uniform (fun n (x : Fin n × (Fin n × (Fin n × Fin n))) =>
decide (x.1 = x.2.1 ∨ x.1 = x.2.2.1 ∨ x.1 = x.2.2.2)) :=
((fst.pair (snd.comp fst)).comp finEq).orD
(((fst.pair (snd.comp (snd.comp fst))).comp finEq).orD
((fst.pair (snd.comp (snd.comp snd))).comp finEq))
exact (((fst.comp universeSet).pair snd).comp P.setFilter).congr (fun _ x => by
ext a; simp only [Function.comp_apply,Finset.mem_filter,Finset.mem_univ,true_and,decide_eq_true_eq,
Finset.mem_insert,Finset.mem_singleton])
def triples : Uniform (fun n (_ : Universe n) =>
(Structure.tripleList (List.finRange n)).map Subtype.val) := by
let E := (universeList.pair (universeList.pair universeList |>.comp product)).comp product
let A := (E.pair id).comp (swap.comp tripleSet).map
let P : Uniform (fun n (x : Finset (Fin n) × Unit) => decide (x.1.card = 3)) :=
(((fst.comp setCard).pair (constant 3)).comp (Realizer.eqNat.uniform ℕ))
exact ((A.pair unit).comp P.filter).congr (fun n _ => by
dsimp only [Function.comp_apply]
simp only [Structure.tripleList,List.product,List.map_flatMap,List.map_map,List.map_filterMap]
rw [← List.filterMap_eq_filter]
congr 1
funext Z
by_cases h : Z.card = 3 <;> simp [Option.guard,h])
def predecessorCount : Uniform (fun n (x : Universe n × (Matrix n × Fin n)) =>
Structure.predecessorCount (matrixRel x.2.1) x.2.2) :=
((((fst.comp universeSet).pair snd).comp
(((snd.comp fst).pair (fst.pair (snd.comp snd))).comp matrixGet).setFilter).comp setCard).congr
(fun _ _ => rfl)
def predecessors : Uniform (fun n (x : Universe n × Matrix n) =>
Structure.predecessorCount (matrixRel x.2)) :=
((fst.pair id).comp (((snd.comp fst).pair ((snd.comp snd).pair fst)).comp predecessorCount).vectorMap)
def rankFromCounts : Uniform (fun n (x : Universe n × ((Fin n → ℕ) × Fin n)) =>
(Finset.univ.filter (fun y => x.2.1 y < x.2.1 x.2.2 ∨
x.2.1 y = x.2.1 x.2.2 ∧ y < x.2.2)).card+1) := by
let A := (((snd.comp fst).pair fst).comp functionGet :
Uniform (fun n (x : Fin n × ((Fin n → ℕ) × Fin n)) => x.2.1 x.1))
let B := (((snd.comp fst).pair (snd.comp snd)).comp functionGet :
Uniform (fun n (x : Fin n × ((Fin n → ℕ) × Fin n)) => x.2.1 x.2.2))
let C := ((A.pair B).comp natLT)
let D := ((A.pair B).comp (Realizer.eqNat.uniform ℕ))
let E := (((fst.comp finVal).pair ((snd.comp snd).comp finVal)).comp natLT :
Uniform (fun n (x : Fin n × ((Fin n → ℕ) × Fin n)) => decide (x.1 < x.2.2)))
exact ((((fst.comp universeSet).pair snd).comp (C.orD (D.andD E)).setFilter).comp setCard).comp
(Realizer.succ.uniform ℕ) |>.congr (fun _ _ => by
simp only [Function.comp_apply,decide_eq_true_eq,Fin.lt_def])
def rank : Uniform (fun n (x : Universe n × Matrix n) => Structure.jobRank (matrixRel x.2)) :=
((fst.pair (fst.pair predecessors)).comp
(((snd.comp fst).pair ((snd.comp snd).pair fst)).comp rankFromCounts).vectorMap).congr (fun _ _ => by
funext y
simp only [Function.comp_apply,Structure.jobRank,Structure.rankOfKey,Structure.jobKey,
Prod.Lex.toLex_lt_toLex])
def reverseRank : Uniform (fun n (x : Universe n × (Fin n → ℕ)) => fun v => n+1-x.2 v) :=
((fst.pair (((fst.comp universeNumber).comp (Realizer.succ.uniform ℕ)).pair snd)).comp
(((snd.comp fst).pair (((snd.comp snd).pair fst).comp functionGet)).comp
(Realizer.sub.uniform ℕ)).vectorMap)
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
open ThreeMachine.Structure ThreeMachine.Algorithm
def coneSet {n : ℕ} (M : Matrix n) (frame : Bool) (kind : Fin 5) (Z : Finset (Fin n)) : Finset (Fin n) :=
let R := fun x y => if frame then matrixRel M y x else matrixRel M x y
match kind.val with
| 0 => Z
| 1 => Finset.univ.filter (fun x => ∃ y ∈ Z, R x y)
| 2 => Finset.univ.filter (fun x => ∃ y ∈ Z, R y x)
| 3 => (Finset.univ.filter (fun x => ∃ y ∈ Z, R x y)) ∪ Z
| _ => (Finset.univ.filter (fun x => ∃ y ∈ Z, R y x)) ∪ Z
theorem atomicCone (n : ℕ) (M : Matrix n) (frame : Bool) (kind : Fin 5)
(Z : {s : Finset (Fin n) // s.card = 3}) :
Atomic.finsetEval (matrixRel M) (Structure.jobRank (matrixRel M))
(Structure.reverseJobRank (matrixRel M)) (.cone frame kind Z) = coneSet M frame kind Z.val := by
fin_cases kind <;> ext x <;> simp [Atomic.finsetEval,coneSet]
theorem map_finRange_nat {β : Type u2} (f : ℕ → β) (k : ℕ) :
(List.finRange k).map (fun i => f i.val) = (List.range k).map f := by
rw [← finRange_val k,List.map_map]
rfl
theorem atomicThreshold {n : ℕ} (M : Matrix n) (frame upper : Bool) :
(List.finRange (Fintype.card (Fin n)+2)).map (fun k =>
Atomic.finsetEval (matrixRel M) (Structure.jobRank (matrixRel M))
(Structure.reverseJobRank (matrixRel M)) (.threshold frame upper k)) =
(List.range (n+2)).map (fun k => Finset.univ.filter (fun v => if upper then
(if frame then Structure.reverseJobRank (matrixRel M) else Structure.jobRank (matrixRel M)) v ≤ k
else k ≤ (if frame then Structure.reverseJobRank (matrixRel M) else Structure.jobRank (matrixRel M)) v)) := by
let f : ℕ → Finset (Fin n) := fun k => Finset.univ.filter (fun v => if upper then
(if frame then Structure.reverseJobRank (matrixRel M) else Structure.jobRank (matrixRel M)) v ≤ k
else k ≤ (if frame then Structure.reverseJobRank (matrixRel M) else Structure.jobRank (matrixRel M)) v)
change (List.finRange (Fintype.card (Fin n)+2)).map (fun k => f k.val) = (List.range (n+2)).map f
rw [map_finRange_nat,Fintype.card_fin]
namespace Uniform
def thresholdSets (upper : Bool) : Uniform (fun n (x : Universe n × (Fin n → ℕ)) =>
(List.range (n+2)).map (fun k => Finset.univ.filter
(fun v => if upper then x.2 v ≤ k else k ≤ x.2 v))) := by
let N : Uniform (fun n (_ : Universe n × (Fin n → ℕ)) => List.range (n+2)) := (((fst.comp universeNumber).pair (constant 2)).comp (Realizer.add.uniform ℕ)).comp
(Realizer.range.uniform ℕ)
let A := (((snd.comp snd).pair fst).comp functionGet :
Uniform (fun n (x : Fin n × (ℕ × (Fin n → ℕ))) => x.2.2 x.1))
let B := (snd.comp fst : Uniform (fun n (x : Fin n × (ℕ × (Fin n → ℕ))) => x.2.1))
let P : Uniform (fun n (x : Fin n × (ℕ × (Fin n → ℕ))) =>
decide (if upper then x.2.2 x.1 ≤ x.2.1 else x.2.1 ≤ x.2.2 x.1)) := by
cases upper
· exact (B.pair A).comp (Realizer.le.uniform ℕ)
· exact (A.pair B).comp (Realizer.le.uniform ℕ)
let F := ((((snd.comp fst).comp universeSet).pair (fst.pair (snd.comp snd))).comp P.setFilter :
Uniform (fun n (x : ℕ × (Universe n × (Fin n → ℕ))) => Finset.univ.filter
(fun v => decide (if upper then x.2.2 v ≤ x.1 else x.1 ≤ x.2.2 v) = true)))
exact ((N.pair id).comp F.map).congr (fun _ _ => by
simp only [Function.comp_apply,decide_eq_true_eq])
def matrixGetFrame (frame : Bool) : Uniform (fun n (x : Matrix n × (Fin n × Fin n)) =>
decide (if frame then matrixRel x.1 x.2.2 x.2.1 else matrixRel x.1 x.2.1 x.2.2)) := by
cases frame
· exact matrixGet.congr (fun _ x => by simp [matrixRel])
· exact ((fst.pair (snd.comp swap)).comp matrixGet).congr (fun _ x => by
simp [Function.comp_apply,matrixRel])
def conePred (frame : Bool) : Uniform (fun n (x : Universe n × (Matrix n × Finset (Fin n))) =>
Finset.univ.filter (fun v => ∃ y ∈ x.2.2,
if frame then matrixRel x.2.1 y v else matrixRel x.2.1 v y)) := by
let A := (((snd.comp fst).pair ((snd.comp snd).pair fst)).comp (matrixGetFrame frame) :
Uniform (fun n (x : Fin n × (Matrix n × Fin n)) =>
decide (if frame then matrixRel x.2.1 x.1 x.2.2 else matrixRel x.2.1 x.2.2 x.1)))
let P := (((snd.comp snd).pair ((snd.comp fst).pair fst)).comp A.setAny)
exact (((fst.comp universeSet).pair snd).comp P.setFilter).congr (fun _ _ => by
simp only [Function.comp_apply,decide_eq_true_eq])
def cone (frame : Bool) (kind : Fin 5) : Uniform (fun n (x : Universe n × (Matrix n × Finset (Fin n))) =>
coneSet x.2.1 frame kind x.2.2) := by
let D : Uniform (fun n (x : Universe n × (Matrix n × Finset (Fin n))) =>
Finset.univ.filter (fun v => ∃ y ∈ x.2.2,
if frame then matrixRel x.2.1 v y else matrixRel x.2.1 y v)) :=
(conePred (!frame)).congr (fun _ x => by cases frame <;> rfl)
match hk : kind.val with
| 0 => exact (snd.comp snd).congr (fun _ _ => by simp only [Function.comp_apply,coneSet,hk])
| 1 => exact (conePred frame).congr (fun _ _ => by simp only [coneSet,hk])
| 2 => exact D.congr (fun _ _ => by simp only [coneSet,hk])
| 3 =>
exact (fst.pair ((conePred frame).pair (snd.comp snd)) |>.comp setUnion).congr
(fun _ _ => by simp only [Function.comp_apply,coneSet,hk])
| k+4 =>
exact (fst.pair (D.pair (snd.comp snd)) |>.comp setUnion).congr
(fun _ _ => by simp only [Function.comp_apply,coneSet,hk])
def cones (frame : Bool) : (ks : List (Fin 5)) →
Uniform (fun n (x : Universe n × Matrix n) => ks.flatMap (fun k =>
((Structure.tripleList (List.finRange n)).map Subtype.val).map (coneSet x.2 frame k)))
| [] => nil
| k :: ks =>
let F := ((((snd.comp fst).pair ((snd.comp snd).pair fst))).comp (cone frame k))
(((((fst.comp triples).pair id).comp F.map).pair (cones frame ks)).comp append).congr
(fun _ _ => rfl)
def ranks (frame : Bool) : Uniform (fun n (x : Universe n × Matrix n) =>
if frame then Structure.reverseJobRank (matrixRel x.2) else Structure.jobRank (matrixRel x.2)) := by
cases frame
· exact rank
· exact (fst.pair rank).comp reverseRank
def thresholds (frame : Bool) : Uniform (fun n (x : Universe n × Matrix n) =>
[Bool.false,true].flatMap (fun upper => (List.range (n+2)).map
(fun k => Finset.univ.filter (fun v => if upper then
(if frame then Structure.reverseJobRank (matrixRel x.2) else Structure.jobRank (matrixRel x.2)) v ≤ k
else k ≤ (if frame then Structure.reverseJobRank (matrixRel x.2) else Structure.jobRank (matrixRel x.2)) v)))) :=
((fst.pair (ranks frame)).comp ((thresholdSets Bool.false).pair (thresholdSets true) |>.comp append)).congr
(fun _ _ => by simp only [Function.comp_apply,List.flatMap_cons,List.flatMap_nil,List.append_nil])
def atomSets : Uniform (fun n (x : Universe n × Matrix n) =>
(Atomic.alphabet (List.finRange n)).map
(Atomic.finsetEval (matrixRel x.2) (Structure.jobRank (matrixRel x.2)) (Structure.reverseJobRank (matrixRel x.2)))) := by
let C : Uniform (fun n (_ : Universe n × Matrix n) => [∅, (Finset.univ : Finset (Fin n))]) := (((fst.comp setEmpty).pair (((fst.comp universeSet).pair nil).comp cons)).comp cons)
let T := ((thresholds Bool.false).pair (thresholds true)).comp append
let D := ((cones Bool.false (List.finRange 5)).pair (cones true (List.finRange 5))).comp append
exact ((C.pair T).comp append |>.pair D |>.comp append).congr (fun n x => by
simp only [Function.comp_apply,Atomic.alphabet,List.map_append,List.map_cons,List.map_nil,
List.map_flatMap,List.map_map,List.flatMap_cons,List.flatMap_nil,List.append_nil,Function.comp_def]
simp only [atomicCone,atomicThreshold]
rfl)
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.Structure
theorem assignments_map {A B : Type} (g : A → B) (xs : List A) (k : ℕ) :
assignments (xs.map g) k = (assignments xs k).map (fun f => g ∘ f) := by
induction k with
| zero => simp only [assignments,List.map_singleton]; congr 1; funext i; exact Fin.elim0 i
| succ k ih =>
simp only [assignments,ih,List.flatMap_map,List.map_flatMap,List.map_map]
apply List.flatMap_congr
intro a ha
apply List.map_congr_left
intro f hf
funext i
refine Fin.cases ?_ (fun j => ?_) i <;> rfl
theorem Formula.map_evalFinset {J A B : Type} [Fintype J] [DecidableEq J]
(g : A → B) (atoms : B → Finset J) (p : Formula A) :
(p.map g).evalFinset atoms = p.evalFinset (atoms ∘ g) := by
induction p with
| leaf a b => rfl
| conj p q ihp ihq | disj p q ihp ihq => simp only [map,evalFinset,ihp,ihq]
theorem Atomic.filter_eval {J : Type} [Fintype J] [DecidableEq J]
(r : J → J → Prop) [DecidableRel r] (rank reverseRank : J → ℕ) (a : Atomic J) :
Finset.univ.filter (eval r rank reverseRank a) = finsetEval r rank reverseRank a := by
apply Finset.coe_injective
rw [coe_finsetEval]
ext x
exact Finset.mem_filter.trans (and_iff_right (Finset.mem_univ x))
theorem effectiveFamily_eq_finset {J : Type} [Fintype J] [DecidableEq J]
(r : J → J → Prop) [DecidableRel r] (rank reverseRank : J → ℕ) (jobs : List J) (K : ℕ) :
effectiveFamily r rank reverseRank jobs K =
(assignments ((Atomic.alphabet jobs).map (Atomic.finsetEval r rank reverseRank)) K).flatMap
(fun f => (Formula.templates K).map (Formula.evalFinset f)) := by
simp only [effectiveFamily,Atomic.filter_eval,assignments_map,List.flatMap_map]
apply List.flatMap_congr
intro f hf
apply List.map_congr_left
intro s hs
exact Formula.map_evalFinset f _ s
end ThreeMachine.Structure
namespace ThreeMachine.StackCompiler
open ThreeMachine.Structure ThreeMachine.Algorithm
namespace Uniform
def evalTemplate {K : ℕ} : (p : Formula (Fin K)) →
Uniform (fun n (x : Universe n × (Fin K → Finset (Fin n))) => p.evalFinset x.2)
| .leaf a b =>
let A := (snd.pair (constant a)).comp (functionGetAny (fun _ : ℕ => K))
if hb : b then
((fst.pair A).comp setCompl).congr (fun _ _ => by simp [Formula.evalFinset,hb,Function.comp_apply])
else A.congr (fun _ _ => by simp [Formula.evalFinset,hb,Function.comp_apply])
| .conj p q => ((evalTemplate p).pair (evalTemplate q)).comp setInter
| .disj p q => (fst.pair ((evalTemplate p).pair (evalTemplate q))).comp setUnion
def evalTemplates {K : ℕ} : (ps : List (Formula (Fin K))) →
Uniform (fun n (x : Universe n × (Fin K → Finset (Fin n))) => ps.map (Formula.evalFinset x.2))
| [] => nil
| p :: ps => ((evalTemplate p).pair (evalTemplates ps)).comp cons
def family (K : ℕ) : Uniform (fun n (x : Universe n × Matrix n) =>
effectiveFamily (matrixRel x.2) (Structure.jobRank (matrixRel x.2))
(Structure.reverseJobRank (matrixRel x.2)) (List.finRange n) K) :=
((((atomSets.comp (assignments K)).pair fst).comp (swap.comp (evalTemplates (Formula.templates K))).flatMap)).congr
(fun _ _ => (effectiveFamily_eq_finset _ _ _ _ _).symm)
def fullSolveK (K : ℕ) : Uniform (fun n (x : Universe n × Matrix n) =>
Algorithm.lookup (Algorithm.layers (matrixRel x.2)
(effectiveFamily (matrixRel x.2) (Structure.jobRank (matrixRel x.2))
(Structure.reverseJobRank (matrixRel x.2)) (List.finRange n) K)
((Structure.tripleList (List.finRange n)).map Subtype.val) n) Finset.univ) := by
let A : Uniform (fun n (x : Universe n × Matrix n) =>
Algorithm.layers (matrixRel x.2) (effectiveFamily (matrixRel x.2) (Structure.jobRank (matrixRel x.2))
(Structure.reverseJobRank (matrixRel x.2)) (List.finRange n) K)
((Structure.tripleList (List.finRange n)).map Subtype.val) n) :=
(((fst.comp universeNumber).pair (fst.pair (snd.pair ((family K).pair (fst.comp triples))))).comp layers)
exact ((A.pair (fst.comp universeSet)).comp (lookupA setEq)).congr (fun _ _ => rfl)
def fullSolve : Uniform (fun n (x : Universe n × Matrix n) => Algorithm.fullSolve (matrixRel x.2)) :=
fullSolveK 10000
end Uniform
end ThreeMachine.StackCompiler
end
end OAI
end
section
-- module ScheduleRoutines
namespace OAI
universe u1 u2 u3 u4
section
namespace ThreeMachine.StackCompiler
open ThreeMachine.Algorithm
instance {n : ℕ} (G : Instance n) : DecidableRel G.edge := fun a b =>
inferInstanceAs (Decidable ((a,b) ∈ G.edges))
instance (n : ℕ) : Coding (Instance n) := ⟨fun G => enc G.edges⟩
@[simp] theorem enc_instance {n : ℕ} (G : Instance n) : enc G = enc G.edges := rfl
theorem enc_map_eq {α : Type u1} {β : Type u2} [Coding α] [Coding β] (f : α → β)
(h : ∀ a, enc (f a) = enc a) (xs : List α) : enc (xs.map f) = enc xs := by
induction xs with
| nil => rfl
| cons a xs ih => simp only [List.map_cons,enc_cons,h,ih]
namespace Uniform
variable {I : Type u3} {α : I → Type u4} [∀ i, Coding (α i)]
def matrixMapAny (d : I → ℕ) {p : ∀ i, (Fin (d i) × Fin (d i)) × α i → Bool}
(P : Uniform p) : Uniform (fun i (x : Universe (d i) × α i) =>
(fun a b => p i ((a,b),x.2) : Matrix (d i))) := by
let A : Uniform (fun i (x : Fin (d i) × (Fin (d i) × α i)) => p i ((x.2.1,x.1),x.2.2)) :=
(((snd.comp fst).pair fst).pair (snd.comp snd)).comp P
let B : Uniform (fun i (x : Fin (d i) × (Universe (d i) × α i)) =>
fun b => p i ((x.1,b),x.2.2)) :=
(((snd.comp fst).pair (fst.pair (snd.comp snd))).comp (A.vectorMapAny d))
exact ((fst.pair id).comp (B.vectorMapAny d)).congr (fun _ _ => rfl)
def instanceEdges : Uniform (fun n (G : Instance n) => G.edges) :=
reinterpret _ (fun _ _ => rfl)
def edgePairEq : Uniform (fun n (x : (Fin n × Fin n) × (Fin n × Fin n)) => decide (x.1 = x.2)) :=
(((fst.comp fst).pair (snd.comp fst)).comp finEq).andD
(((fst.comp snd).pair (snd.comp snd)).comp finEq) |>.congr (fun _ x => by
apply decide_eq_decide.mpr
change (x.1.1 = x.2.1 ∧ x.1.2 = x.2.2) ↔ x.1 = x.2
exact Prod.ext_iff.symm)
def edgeAt : Uniform (fun n (x : (Fin n × Fin n) × Instance n) => decide (x.2.edge x.1.1 x.1.2)) :=
((((snd.comp instanceEdges).pair fst).comp edgePairEq.any)).congr (fun _ x => by
simp only [Function.comp_apply]
apply Bool.eq_iff_iff.mpr
rw [decide_eq_true_eq]
simp only [List.any_eq_true,decide_eq_true_eq]
change (∃ y ∈ x.2.edges, y = x.1) ↔ x.1 ∈ x.2.edges
exact exists_eq_right)
def edgeMatrix : Uniform (fun n (x : Universe n × Instance n) =>
(fun a b => decide (x.2.edge a b) : Matrix n)) := matrixMapAny (fun n : ℕ => n) edgeAt
def matrixRows : Uniform (fun n (M : Matrix n) => (List.ofFn M).map List.ofFn) :=
reinterpret _ (fun _ M => by
rw [enc_map_eq List.ofFn (fun _ => rfl)]
rfl)
def readMatrix {n : ℕ} (M : Matrix n) (a b : ℕ) : Bool :=
(((List.ofFn M).map List.ofFn).getD a []).getD b Bool.false
def matrixReadNat : Uniform (fun n (x : Matrix n × (ℕ × ℕ)) => readMatrix x.1 x.2.1 x.2.2) := by
let A := ((((fst.comp matrixRows).pair (snd.comp fst)).pair nil).comp getElemD :
Uniform (fun n (x : Matrix n × (ℕ × ℕ)) => ((List.ofFn x.1).map List.ofFn).getD x.2.1 []))
exact (((A.pair (snd.comp snd)).pair false).comp getElemD)
theorem readMatrix_eq {n : ℕ} (M : Matrix n) (a b : ℕ) :
readMatrix M a b = if ha : a < n then if hb : b < n then M ⟨a,ha⟩ ⟨b,hb⟩ else Bool.false else Bool.false := by
simp only [readMatrix,List.getD_eq_getElem?_getD,List.getElem?_map,List.getElem?_ofFn]
split_ifs <;> simp_all
def paddedMatrix : Uniform (fun (i : ℕ × ℕ) (x : Universe i.2 × Matrix i.1) =>
(fun a b => decide (paddedOrder (matrixRel x.2) i.2 a b) : Matrix i.2)) := by
let P : Uniform (fun (i : ℕ × ℕ) (x : (Fin i.2 × Fin i.2) × Matrix i.1) =>
readMatrix x.2 x.1.1.val x.1.2.val) :=
(snd.pair (((fst.comp fst).comp (finValue Prod.snd)).pair
((fst.comp snd).comp (finValue Prod.snd)))).comp (matrixReadNat.reindex Prod.fst)
exact (matrixMapAny Prod.snd P).congr (fun i x => by
funext a b
rw [readMatrix_eq]
by_cases ha : a.val < i.1 <;> by_cases hb : b.val < i.1
· simp only [dite_eq_left ha,dite_eq_left hb]
apply Bool.eq_iff_iff.mpr
change (x.2 ⟨a.val,ha⟩ ⟨b.val,hb⟩ = true) ↔
(decide (paddedOrder (matrixRel x.2) i.2 a b) = true)
rw [decide_eq_true_eq]
change (matrixRel x.2 ⟨a.val,ha⟩ ⟨b.val,hb⟩) ↔ paddedOrder (matrixRel x.2) i.2 a b
constructor
· intro h; exact ⟨⟨a.val,ha⟩,⟨b.val,hb⟩,rfl,rfl,h⟩
· rintro ⟨u,v,hu,hv,h⟩
have eu : u = ⟨a.val,ha⟩ := Fin.ext hu.symm
have ev : v = ⟨b.val,hb⟩ := Fin.ext hv.symm
simpa only [eu,ev] using h
· simp only [dite_eq_left ha,dite_eq_right hb]
have h : ¬paddedOrder (matrixRel x.2) i.2 a b := by
rintro ⟨u,v,hu,hv,hr⟩; exact hb (hv.symm ▸ v.isLt)
simp only [h,decide_false]
· simp only [dite_eq_right ha]
have h : ¬paddedOrder (matrixRel x.2) i.2 a b := by
rintro ⟨u,v,hu,hv,hr⟩; exact ha (hu.symm ▸ u.isLt)
simp only [h,decide_false]
· simp only [dite_eq_right ha]
have h : ¬paddedOrder (matrixRel x.2) i.2 a b := by
rintro ⟨u,v,hu,hv,hr⟩; exact ha (hu.symm ▸ u.isLt)
simp only [h,decide_false])
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
open ThreeMachine.Algorithm
def nextMatrix {n : ℕ} (E M : Matrix n) : Matrix n :=
fun a b => M a b || (List.finRange n).any (fun z => M a z && E z b)
def closureMatrix {n : ℕ} (G : Instance n) (k : ℕ) : Matrix n :=
fun a b => decide ((a,b) ∈ Algorithm.closureTable G k)
theorem closureMatrix_zero {n : ℕ} (G : Instance n) :
closureMatrix G 0 = fun a b => decide (G.edge a b) := by
funext a b
simp only [closureMatrix,Algorithm.closureTable_zero,List.mem_toFinset,Instance.edge]
rfl
theorem nextMatrix_closure {n : ℕ} (G : Instance n) (k : ℕ) :
nextMatrix (closureMatrix G 0) (closureMatrix G k) = closureMatrix G (k+1) := by
funext a b
apply Bool.eq_iff_iff.mpr
simp only [nextMatrix,closureMatrix,Bool.or_eq_true,Bool.and_eq_true,List.any_eq_true,
decide_eq_true_eq,List.mem_finRange]
simp only [Algorithm.closureTable_succ,Algorithm.closureTable_zero,
Algorithm.closureStep,Finset.mem_union,Finset.mem_filter,Finset.mem_univ,true_and]
namespace Uniform
def nextMatrixCell : Uniform (fun n (x : (Fin n × Fin n) × (Universe n × (Matrix n × Matrix n))) =>
ThreeMachine.StackCompiler.nextMatrix x.2.2.1 x.2.2.2 x.1.1 x.1.2) := by
let P : Uniform (fun n (x : Fin n × ((Fin n × Fin n) × (Matrix n × Matrix n))) =>
x.2.2.2 x.2.1.1 x.1 && x.2.2.1 x.1 x.2.1.2) :=
(((((snd.comp (snd.comp snd)).pair (((snd.comp (fst.comp fst)).pair fst))).comp matrixGet).pair
(((snd.comp (snd.comp fst)).pair (fst.pair (snd.comp (fst.comp snd)))).comp matrixGet)).comp
(Realizer.and.uniform ℕ))
let A := (((snd.comp (snd.comp snd)).pair fst).comp matrixGet :
Uniform (fun n (x : (Fin n × Fin n) × (Universe n × (Matrix n × Matrix n))) =>
x.2.2.2 x.1.1 x.1.2))
let B := ((((snd.comp fst).comp universeList).pair (fst.pair (snd.comp snd))).comp P.any)
exact ((A.pair B).comp (Realizer.or.uniform ℕ)).congr (fun _ _ => rfl)
def nextMatrix : Uniform (fun n (x : Universe n × (Matrix n × Matrix n)) =>
ThreeMachine.StackCompiler.nextMatrix x.2.1 x.2.2) :=
(fst.pair id).comp (matrixMapAny (fun n => n) nextMatrixCell)
def closureMatrixStep : Uniform (fun n (x : (Universe n × Matrix n) × Matrix n) =>
(x.1,ThreeMachine.StackCompiler.nextMatrix x.1.2 x.2)) :=
fst.pair ((((fst.comp fst).pair ((fst.comp snd).pair snd))).comp nextMatrix)
def reachMatrix : Uniform (fun n (x : Universe n × Instance n) => closureMatrix x.2 n) := by
let A := fst.pair edgeMatrix
let B := ((fst.comp universeNumber).pair (A.pair edgeMatrix)).comp closureMatrixStep.iterate |>.comp snd
exact B.congr (fun n x => by
dsimp only [Function.comp_apply]
have h : ∀ k, (fun p : (Universe n × Matrix n) × Matrix n =>
(p.1,ThreeMachine.StackCompiler.nextMatrix p.1.2 p.2))^[k]
((x.1,fun a b => decide (x.2.edge a b)),fun a b => decide (x.2.edge a b)) =
((x.1,fun a b => decide (x.2.edge a b)),closureMatrix x.2 k) := by
intro k
induction k with
| zero => rw [Function.iterate_zero_apply,closureMatrix_zero]
| succ k ih =>
rw [Function.iterate_succ_apply',ih]
simp only [← closureMatrix_zero,nextMatrix_closure]
rw [h])
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
open ThreeMachine.Algorithm
namespace Realizer
def triple : Realizer (fun n : ℕ => 3*n) :=
(((id.pair id).comp add).pair id |>.comp add).congr (fun n => by
simp only [Function.comp_apply,id_eq]
omega)
end Realizer
def scheduleMatrix {n : ℕ} (M : Matrix n) (T : ℕ) : Option (Fin n → ℕ) :=
if hn : n ≤ 3*T then
(Algorithm.fullSolve (paddedOrder (matrixRel M) (3*T))).map
(fun s x => s.time (Fin.castLE hn x))
else none
theorem scheduleMatrix_closure {n : ℕ} (G : Instance n) (T : ℕ) :
scheduleMatrix (closureMatrix G n) T = Algorithm.scheduleAt G T := by
have h : matrixRel (closureMatrix G n) = Algorithm.reachable G := by
funext a b
simp only [matrixRel,closureMatrix,decide_eq_true_eq,Algorithm.reachable]
simp only [scheduleMatrix,Algorithm.scheduleAt,h]
namespace Uniform
def restrictTime : Uniform (fun (i : ℕ × ℕ) (x : Universe i.1 × (Fin i.2 → ℕ)) =>
(fun v : Fin i.1 => (List.ofFn x.2).getD v.val 0)) := by
let A : Uniform (fun (i : ℕ × ℕ) (x : Fin i.1 × (Fin i.2 → ℕ)) =>
(List.ofFn x.2).getD x.1.val 0) :=
((((snd.comp (functionListAny Prod.snd)).pair (fst.comp (finValue Prod.fst))).pair zero).comp getElemD)
exact A.vectorMapAny Prod.fst
def paddedSolve : Uniform (fun (i : ℕ × ℕ) (x : Cardinal i.2 × Matrix i.1) =>
Algorithm.fullSolve (paddedOrder (matrixRel x.2) (3*i.2))) := by
let U : Uniform (fun (i : ℕ × ℕ) (_ : Cardinal i.2 × Matrix i.1) =>
(Universe.mk () : Universe (3*i.2))) := (fst.comp (cardinalMap Prod.snd Realizer.triple)).comp
(makeUniverseAny (fun i : ℕ × ℕ => 3*i.2))
let A := (U.pair snd).comp (paddedMatrix.reindex (fun i : ℕ × ℕ => (i.1,3*i.2)))
exact ((U.pair A).comp (fullSolve.reindex (fun i : ℕ × ℕ => 3*i.2))).congr (fun i x => by
have h : matrixRel (fun a b : Fin (3*i.2) => decide (paddedOrder (matrixRel x.2) (3*i.2) a b)) =
paddedOrder (matrixRel x.2) (3*i.2) := by
funext a b
exact propext (by simp only [matrixRel,decide_eq_true_eq])
simp only [Function.comp_apply,h])
def scheduleMatrixFixed : Uniform (fun (i : ℕ × ℕ)
(x : Universe i.1 × (Cardinal i.2 × Matrix i.1)) =>
ThreeMachine.StackCompiler.scheduleMatrix x.2.2 i.2) := by
let P : Uniform (fun (i : ℕ × ℕ) (_ : Universe i.1 × (Cardinal i.2 × Matrix i.1)) =>
decide (i.1 ≤ 3*i.2)) :=
(((fst.comp (universeNumber.reindex Prod.fst)).pair
((snd.comp fst).comp (cardinalValue Prod.snd) |>.comp (Realizer.triple.uniform (ℕ × ℕ)))).comp
(Realizer.le.uniform (ℕ × ℕ)))
let R : Uniform (fun (i : ℕ × ℕ) (x : Algorithm.Block (Fin (3*i.2)) × Universe i.1) =>
(fun v : Fin i.1 => (List.ofFn x.1.time).getD v.val 0)) :=
(snd.pair (fst.comp (blockTime.reindex (fun i : ℕ × ℕ => 3*i.2)))).comp
(restrictTime.reindex (fun i : ℕ × ℕ => (i.1,3*i.2)))
let A := (((snd.comp paddedSolve).pair fst).comp R.optionMap)
exact ((P.pair id).comp (A.choose none)).congr (fun i x => by
simp only [Function.comp_apply,ThreeMachine.StackCompiler.scheduleMatrix]
by_cases h : i.1 ≤ 3*i.2
· simp only [decide_eq_true_eq,ite_eq_left h,dite_eq_left h]
apply congrArg (fun f => Option.map f _)
funext b
funext v
simp only [List.getD_eq_getElem?_getD,List.getElem?_ofFn,dite_eq_left (lt_of_lt_of_le v.isLt h),
Option.getD_some]
rfl
· simp only [decide_eq_true_eq,ite_eq_right h,dite_eq_right h])
def scheduleMatrix : Uniform (fun n (x : Universe n × (ℕ × Matrix n)) =>
ThreeMachine.StackCompiler.scheduleMatrix x.2.2 x.2.1) :=
scheduleMatrixFixed.recode _ (fun n x =>
⟨(n,x.2.1),(x.1,(Cardinal.mk (),x.2.2)),rfl,rfl⟩)
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
open ThreeMachine.Algorithm
def bestMatrix {n : ℕ} (M : Matrix n) : ℕ → Option (ℕ × (Fin n → ℕ))
| 0 => none
| k+1 => match bestMatrix M k with
| some a => some a
| none => (scheduleMatrix M (k+1)).map (fun t => (k+1,t))
theorem bestMatrix_closure {n : ℕ} (G : Instance n) (k : ℕ) :
bestMatrix (closureMatrix G n) k = Algorithm.best G k := by
induction k with
| zero => rfl
| succ k ih =>
simp only [bestMatrix,Algorithm.best,ih,scheduleMatrix_closure]
try cases Algorithm.best G k <;> rfl
def bestMatrixStep {n : ℕ}
(x : (Universe n × Matrix n) × (ℕ × Option (ℕ × (Fin n → ℕ)))) :=
(x.1,(x.2.1+1,match x.2.2 with
| some a => some a
| none => (scheduleMatrix x.1.2 (x.2.1+1)).map (fun t => (x.2.1+1,t))))
theorem bestMatrix_iterate {n : ℕ} (U : Universe n) (M : Matrix n) (k : ℕ) :
bestMatrixStep^[k] ((U,M),(0,none)) = ((U,M),(k,bestMatrix M k)) := by
induction k with
| zero => rfl
| succ k ih => rw [Function.iterate_succ_apply',ih]; rfl
def answerMatrix {n : ℕ} (M : Matrix n) : Option ℕ → Option (List ℕ)
| some T => (scheduleMatrix M T).map List.ofFn
| none => (bestMatrix M n).map (fun a => List.ofFn a.2)
theorem answerMatrix_closure {n : ℕ} (G : Instance n) (d : Option ℕ) :
encodeAnswer (answerMatrix (closureMatrix G n) d) = Algorithm.output G d := by
cases d <;> simp only [answerMatrix,Algorithm.output,scheduleMatrix_closure,bestMatrix_closure,slots]
all_goals rfl
namespace Uniform
def bestMatrixStep : Uniform (fun n => @ThreeMachine.StackCompiler.bestMatrixStep n) := by
let K := ((snd.comp fst).comp (Realizer.succ.uniform ℕ) :
Uniform (fun n (x : (Universe n × Matrix n) × (ℕ × Option (ℕ × (Fin n → ℕ)))) => x.2.1+1))
let A := ((((fst.comp fst).pair (K.pair (fst.comp snd))).comp scheduleMatrix).pair K).comp
swap.optionMap
let R := ((((snd.comp snd).comp optionIsSome).pair id).comp ((snd.comp snd).choose A))
exact (fst.pair (K.pair R)).congr (fun n x => by
simp only [Function.comp_apply,ThreeMachine.StackCompiler.bestMatrixStep]
cases x.2.2 <;> rfl)
def bestMatrix : Uniform (fun n (x : Universe n × Matrix n) =>
ThreeMachine.StackCompiler.bestMatrix x.2 n) :=
((((fst.comp universeNumber).pair (id.pair (zero.pair none))).comp bestMatrixStep.iterate).comp
(snd.comp snd)).congr (fun n x => by
rcases x with ⟨U,M⟩
simp only [Function.comp_apply,bestMatrix_iterate])
def answerMatrix : Uniform (fun n (x : Universe n × (Matrix n × Option ℕ)) =>
ThreeMachine.StackCompiler.answerMatrix x.2.1 x.2.2) := by
let T := ((((snd.comp snd).pair zero).comp getD) :
Uniform (fun n (x : Universe n × (Matrix n × Option ℕ)) => x.2.2.getD 0))
let A : Uniform (fun n (x : Universe n × (Matrix n × Option ℕ)) =>
(ThreeMachine.StackCompiler.scheduleMatrix x.2.1 (x.2.2.getD 0)).map List.ofFn) :=
((fst.pair (T.pair (snd.comp fst))).comp scheduleMatrix).comp functionList.mapOption
let B : Uniform (fun n (x : Universe n × (Matrix n × Option ℕ)) =>
(ThreeMachine.StackCompiler.bestMatrix x.2.1 n).map (fun a => List.ofFn a.2)) :=
((fst.pair (snd.comp fst)).comp bestMatrix).comp (snd.comp functionList).mapOption
exact ((((snd.comp snd).comp optionIsSome).pair id).comp (A.choose B)).congr (fun n x => by
dsimp only [Function.comp_apply]
cases x.2.2 <;> rfl)
def unaryAnswer : Uniform (fun n (x : Universe n × (Instance n × Option ℕ)) =>
ThreeMachine.StackCompiler.answerMatrix (closureMatrix x.2.1 n) x.2.2) :=
(fst.pair ((((fst.pair (snd.comp fst)).comp reachMatrix).pair (snd.comp snd)))).comp answerMatrix
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.Algorithm
open Structure
namespace Block
def Bounded {J : Type} (s : Block J) : Prop := ∀ x, s.time x ≤ s.length
end Block
namespace State
variable {J : Type} [DecidableEq J]
end State
section Bounded
variable {J : Type} [Fintype J] [DecidableEq J] (r : J → J → Prop) [DecidableRel r]
def TableBounded (tab : List (Finset J × Block J)) : Prop :=
∀ W s, (W,s) ∈ tab → s.Bounded
def MarksBounded (marks : List (State J × Block J)) : Prop :=
∀ u s, (u,s) ∈ marks → s.Bounded
end Bounded
end ThreeMachine.Algorithm
end
end OAI
end
section
-- module CostBounds
namespace OAI
universe u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16 u17 u18 u19 u20 u21 u22 u23 u24 u25 u26 u27 u28 u29 u30 u31 u32 u33 u34 u35 u36 u37 u38 u39 u40
section
namespace ThreeMachine.StackCompiler
@[simp] theorem volume_unit : volume () = 1 := rfl
@[simp] theorem volume_bool_false : volume Bool.false = 1 := rfl
@[simp] theorem volume_bool_true : volume Bool.true = 3 := rfl
@[simp] theorem volume_none {α : Type u1} [Coding α] : volume (none : Option α) = 1 := rfl
@[simp] theorem volume_some {α : Type u2} [Coding α] (a : α) : volume (some a) = volume a+2 := by
simp only [volume,enc_some,Data.size_pair,Data.size_nil]
theorem volume_bool (b : Bool) : volume b ≤ 3 := by cases b <;> decide
theorem volume_mem_le {α : Type u4} [Coding α] {xs : List α} {a : α}
(ha : a ∈ xs) : volume a ≤ volume xs := by
induction xs with
| nil => simp at ha
| cons b xs ih =>
simp only [List.mem_cons] at ha
rcases ha with rfl | ha
· simp only [volume_cons]; omega
· have := ih ha; simp only [volume_cons]; omega
theorem volume_option_le {α : Type u7} [Coding α] (o : Option α) (V : ℕ)
(hV : ∀ a ∈ o, volume a ≤ V) : volume o ≤ V+2 := by
cases o with
| none => simp only [volume_none]; omega
| some a => simpa only [volume_some,Nat.add_le_add_iff_right] using hV a rfl
theorem volume_optionToList {α : Type u8} [Coding α] (o : Option α) :
volume o.toList = volume o := by cases o <;> rfl
theorem volume_finset_le {n : ℕ} (s : Finset (Fin n)) : volume s ≤ 3*(n+1)^2 := by
change volume (s.sort (· ≤ ·)) ≤ _
have h := volume_list_le (s.sort (· ≤ ·)) (2*n+1) (fun a _ => by
rw [volume_fin]; have := a.isLt; omega)
have hh := Finset.card_le_univ s
rw [Finset.length_sort] at h
simp only [Fintype.card_fin] at hh
nlinarith
namespace Realizer
variable {α : Type u10} {β : Type u11} [Coding α] [Coding β] {f : α × β → β}
theorem foldTime_le (R : Realizer f) (xs : List α) (P : β → Prop) (T V : ℕ)
(hvol : ∀ b, P b → volume b ≤ V)
(hstep : ∀ a ∈ xs, ∀ b, P b → P (f (a,b)))
(htime : ∀ a ∈ xs, ∀ b, P b → R.time (a,b) ≤ T)
(b : β) (hb : P b) :
foldTime R b xs ≤ xs.length*(T+20*(volume xs+2*V+1))+1 := by
induction xs generalizing b with
| nil => simp only [foldTime,List.length_nil,Nat.zero_mul,Nat.zero_add]; rfl
| cons a xs ih =>
have ha : a ∈ a :: xs := by simp
have hs := hstep a ha b hb
have hi := ih (fun a ha => hstep a (by simp [ha]))
(fun a ha => htime a (by simp [ha])) (f (a,b)) hs
have ht := htime a ha b hb
have hv := hvol b hb
have hw := hvol _ hs
simp only [foldTime,volume_cons,List.length_cons] at hi ⊢
nlinarith [volume_pos a,volume_pos xs]
end Realizer
namespace Uniform
variable {I : Type u12} {α : I → Type u13} {β : I → Type u14} [∀ i, Coding (α i)] [∀ i, Coding (β i)]
variable {f : ∀ i, α i × β i → β i}
theorem time_fold_le (R : Uniform f) (i : I) (xs : List (α i))
(P : β i → Prop) (T V : ℕ) (hvol : ∀ b, P b → volume b ≤ V)
(hstep : ∀ a ∈ xs, ∀ b, P b → P (f i (a,b)))
(htime : ∀ a ∈ xs, ∀ b, P b → R.time i (a,b) ≤ T)
(b : β i) (hb : P b) :
R.fold.time i (xs,b) ≤ 50*(xs.length+1)*(T+volume xs+V+1) := by
have h := Realizer.foldTime_le (R.specialize i) xs P T V hvol hstep htime b hb
rw [time_fold]
simp only [volume_pair]
have hv := hvol b hb
nlinarith [volume_pos xs]
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
namespace Realizer
theorem time_not_le (b : Bool) : not.time b ≤ 10000 := by cases b <;> decide
theorem time_and_le (x : Bool × Bool) : and.time x ≤ 10000 := by
rcases x with ⟨a,b⟩; cases a <;> cases b <;> decide
theorem time_or_le (x : Bool × Bool) : or.time x ≤ 10000 := by
rcases x with ⟨a,b⟩; cases a <;> cases b <;> decide
theorem time_succ_le (n : ℕ) : succ.time n ≤ 200*(n+1) := by
have hu : (unit : Realizer (fun (_ : ℕ) => ())).time n = 2 := rfl
simp only [succ,time_congr,time_comp,time_pair,time_id,hu,id_eq]
simp only [volume_pair,volume_unit,volume_nat]
change 2+(2*n+1+2)+20*((2*n+1)+1+(2*n+1)+1)+(volume ((),n)+2)+10*(1+(2*n+1)+1+1) ≤ _
simp only [volume_pair,volume_unit,volume_nat]
omega
theorem time_test_le {α : Type u15} [Coding α] (p : α → Bool)
(h : ∀ x, (enc x).nonempty = p x) (x : α) :
(test p h).time x ≤ 10000*(volume x+1) := by
simp only [time,test,Routine.comp,Routine.pair,Routine.identity,Routine.nil,
Routine.choose,Routine.constant,Data.size_pair,Data.size_nil]
change (enc x).size+2+2+20*((enc x).size+(enc x).size+1+1)+
(7*(20*((enc x).size+1+1)+50*3+50)+2+30*((enc x).size+1+1+3+1+1))+
10*((enc x).size+1+1+1) ≤ _
change _ ≤ 10000*((enc x).size+1)
omega
end Realizer
namespace Uniform
variable {I : Type u16} {α : I → Type u17} {β : I → Type u18}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)]
@[simp] theorem time_uniform {δ : Type u19} {ε : Type u20} [Coding δ] [Coding ε]
{f : δ → ε} (R : Realizer f) (i : I) (x : δ) : (R.uniform I).time i x = R.time x := rfl
theorem time_head?_le (i : I) (xs : List (α i)) : head?.time i xs ≤ 10000*(volume xs+1) := by
cases xs with
| nil =>
simp only [time,head?,Routine.comp,Routine.pair,Routine.identity,Routine.nil,
Routine.choose,Routine.select,enc_nil,id_eq,Function.comp_apply,
ite_true,Data.head,Data.size_pair,Data.size_nil,volume,enc_nil]
omega
| cons a xs =>
dsimp only [time,head?,Routine.comp,Routine.pair,Routine.identity,Routine.nil,
Routine.choose,Routine.select,Function.comp_apply,enc_cons,Data.head,Data.tail,
Data.size_pair,Data.size_nil,Data.nonempty,id_eq,ite_true]
simp only [ite_true,Data.size_pair,Data.size_nil,volume,enc_cons,Data.size_pair]
omega
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
def Majorized {I : Type u21} (f g : I → ℕ) : Prop := ∃ C : ℕ, ∀ i, f i ≤ C*g i
namespace Majorized
variable {I : Type u22} {J : Type u23} {f g h s t : I → ℕ}
theorem refl (f : I → ℕ) : Majorized f f := ⟨1,fun _ => by omega⟩
theorem of_le (h : ∀ i, f i ≤ g i) : Majorized f g := ⟨1,fun i => by simpa using h i⟩
theorem trans (hf : Majorized f g) (hg : Majorized g h) : Majorized f h := by
obtain ⟨C,hC⟩ := hf; obtain ⟨D,hD⟩ := hg
exact ⟨C*D,fun i => (hC i).trans (by simpa only [Nat.mul_assoc] using Nat.mul_le_mul_left C (hD i))⟩
theorem precomp (hf : Majorized f g) (a : J → I) : Majorized (f ∘ a) (g ∘ a) := by
obtain ⟨C,hC⟩ := hf; exact ⟨C,fun i => hC (a i)⟩
theorem add (hf : Majorized f s) (hg : Majorized g s) : Majorized (fun i => f i+g i) s := by
obtain ⟨C,hC⟩ := hf; obtain ⟨D,hD⟩ := hg
refine ⟨C+D,fun i => ?_⟩
simpa only [Nat.add_mul] using Nat.add_le_add (hC i) (hD i)
theorem mul (hf : Majorized f s) (hg : Majorized g t) :
Majorized (fun i => f i*g i) (fun i => s i*t i) := by
obtain ⟨C,hC⟩ := hf; obtain ⟨D,hD⟩ := hg
refine ⟨C*D,fun i => ?_⟩
simpa only [Nat.mul_assoc,Nat.mul_left_comm,Nat.mul_comm] using Nat.mul_le_mul (hC i) (hD i)
theorem const (C : ℕ) (hs : ∀ i, 1 ≤ s i) : Majorized (fun _ => C) s := by
exact ⟨C,fun i => by simpa using Nat.mul_le_mul_left C (hs i)⟩
theorem pow (hf : Majorized f s) (d : ℕ) : Majorized (fun i => (f i)^d) (fun i => (s i)^d) := by
obtain ⟨C,hC⟩ := hf
refine ⟨C^d,fun i => ?_⟩
simpa only [Nat.mul_pow] using Nat.pow_le_pow_left (hC i) d
theorem pow_mono (hs : ∀ i, 1 ≤ s i) {d e : ℕ} (hde : d ≤ e) :
Majorized (fun i => (s i)^d) (fun i => (s i)^e) :=
of_le (fun i => Nat.pow_le_pow_right (hs i) hde)
end Majorized
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
@[simp] theorem volume_flatten {α : Type u24} [Coding α] (xs : List (List α)) :
volume xs = volume xs.flatten+2*xs.length := by
induction xs with
| nil => rfl
| cons a xs ih =>
have h := volume_append a xs.flatten
simp only [volume_cons,List.flatten_cons,List.length_cons] at ih ⊢
omega
namespace Uniform
variable {I : Type u25} {α : I → Type u26} {β : I → Type u27} {γ : I → Type u28}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
@[simp] theorem time_tail (i : I) (xs : List (α i)) : tail.time i xs = volume xs+2 := rfl
@[simp] theorem time_none (i : I) (x : α i) : (none : Uniform (fun i (_ : α i) => (Option.none : Option (β i)))).time i x = 2 := rfl
theorem time_ite_le {p : ∀ i, α i → Bool} {f g : ∀ i, α i → β i}
(P : Uniform p) (R : Uniform f) (S : Uniform g) (i : I) (x : α i) :
(P.ite R S).time i x ≤ P.time i x+R.time i x+S.time i x+
1000*(volume x+volume (f i x)+volume (g i x)+1) := by
have hp := volume_bool (p i x)
simp only [ite,time_congr,time_comp,time_pair,time_id,time_choose,time_snd,volume_pair]
omega
end Uniform
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Uniform
variable {I : Type u29} {α : I → Type u30} {β : I → Type u31} {γ : I → Type u32}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
theorem time_optionMap {f : ∀ i, α i × γ i → β i} (R : Uniform f)
(i : I) (o : Option (α i)) (e : γ i) (T V : ℕ)
(hT : ∀ a ∈ o, R.time i (a,e) ≤ T) (hV : ∀ a ∈ o, volume (f i (a,e)) ≤ V) :
R.optionMap.time i (o,e) ≤ 1000000*(T+volume o+volume e+V+1) := by
have hl : o.toList.length ≤ 1 := by cases o <;> simp
have hv : volume (o.toList.map (fun a => f i (a,e))) ≤ V+3 := by
cases o with
| none => simp only [Option.toList_none,List.map_nil,volume_nil]; omega
| some a =>
have hv := hV a rfl
simp only [Option.toList_some,List.map_cons,List.map_nil,volume_cons,volume_nil]
omega
have hm := time_map R i o.toList e T (fun a ha => hT a (by simpa using ha))
have hh := time_head?_le i (o.toList.map (fun a => f i (a,e)))
simp only [optionMap,time_congr,time_comp,onFst,time_pair,optionToList,time_reinterpret,
time_fst,time_snd,Function.comp_apply,volume_pair,volume_optionToList] at hm ⊢
nlinarith [volume_pos o,volume_pos e]
theorem time_getD_le (i : I) (o : Option (α i)) (a : α i) :
getD.time i (o,a) ≤ 10000*(volume o+volume a+1) := by
cases o with
| none =>
simp only [getD,time_congr,time_comp,time_pair,time_fst,time_snd,optionToList,time_reinterpret,
time_fold,Function.comp_apply,Realizer.foldTime,Option.toList_none,volume_pair,volume_none,volume_nil]
omega
| some b =>
simp only [getD,time_congr,time_comp,time_pair,time_fst,time_snd,optionToList,time_reinterpret,
time_fold,Function.comp_apply,Realizer.foldTime,Option.toList_some,volume_pair,volume_some,volume_cons,volume_nil]
simp only [Realizer.time,Uniform.specialize,Uniform.fst,Routine.select,volume,enc_pair,Data.size_pair]
omega
end ThreeMachine.StackCompiler.Uniform
namespace ThreeMachine.StackCompiler.Uniform
variable {I : Type u33} {α : I → Type u34} {β : I → Type u35} {γ : I → Type u36}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
theorem time_anyBody {p : ∀ i, α i × γ i → Bool} (P : Uniform p)
(i : I) (a : α i) (e : γ i) (b : Bool) :
(anyBody P).time i (a,(e,b)) ≤ P.time i (a,e)+100000*(volume a+volume e+1) := by
have hp := volume_bool (p i (a,e))
have hb := volume_bool b
have ho := volume_bool (b || p i (a,e))
have ht := Realizer.time_or_le (b,p i (a,e))
simp only [anyBody,time_pair,time_comp,time_fst,time_snd,time_uniform,volume_pair,Function.comp_apply]
omega
theorem time_any {p : ∀ i, α i × γ i → Bool} (P : Uniform p)
(i : I) (xs : List (α i)) (e : γ i) (T : ℕ)
(hT : ∀ a ∈ xs, P.time i (a,e) ≤ T) :
P.any.time i (xs,e) ≤ 10000000*(xs.length+1)*(T+volume xs+volume e+1) := by
have hf := time_fold_le (anyBody P) i xs (fun b => b.1 = e)
(T+100000*(volume xs+volume e+1)) (volume e+4)
(by rintro ⟨e',b⟩ hb; dsimp only at hb; subst e'; rw [volume_pair]; have := volume_bool b; omega)
(by intro a ha b hb; exact hb)
(by intro a ha b hb
have h := time_anyBody P i a e b.2
have ht := hT a ha
have hv := volume_mem_le ha
subst e
exact h.trans (by omega)) (e,Bool.false) rfl
have hv := volume_bool (xs.any (fun a => p i (a,e)))
simp only [any,time_congr,time_comp,time_pair,time_fst,time_snd,time_false,
Function.comp_apply,any_fold_eq,Bool.false_or,volume_pair,volume_bool_false]
nlinarith [volume_pos xs,volume_pos e]
theorem time_all {p : ∀ i, α i × γ i → Bool} (P : Uniform p)
(i : I) (xs : List (α i)) (e : γ i) (T : ℕ)
(hT : ∀ a ∈ xs, P.time i (a,e) ≤ T) :
P.all.time i (xs,e) ≤ 1000000000000*(xs.length+1)*(T+volume xs+volume e+1) := by
have hf := time_any (P.comp (Realizer.not.uniform I)) i xs e (T+10040) (by
intro a ha
have ht := hT a ha
have hn := Realizer.time_not_le (p i (a,e))
have hv := volume_bool (p i (a,e))
simp only [time_comp,time_uniform]
omega)
have hn := Realizer.time_not_le (xs.any (fun a => !(p i (a,e))))
have hv := volume_bool (xs.any (fun a => !(p i (a,e))))
simp only [all,time_congr,time_comp,time_uniform,Function.comp_apply]
nlinarith [volume_pos xs,volume_pos e]
end ThreeMachine.StackCompiler.Uniform
namespace ThreeMachine.StackCompiler
@[simp] theorem volume_replicate_unit (m : ℕ) : volume (List.replicate m ()) = 2*m+1 := by
change (enc (List.replicate m ())).size = _
rw [Realizer.encode_replicate_unit]
exact volume_nat m
namespace Uniform
variable {I : Type u37} {α : I → Type u38} {β : I → Type u39} {γ : I → Type u40}
variable [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
omit [∀ i, Coding (β i)] [∀ i, Coding (γ i)] in
theorem foldTime_iterate_le {f : ∀ i, α i → α i} (R : Uniform f)
(i : I) (m : ℕ) (a : α i) (T V : ℕ)
(hT : ∀ j < m, R.time i ((f i)^[j] a) ≤ T)
(hV : ∀ j ≤ m, volume ((f i)^[j] a) ≤ V) :
Realizer.foldTime ((snd.comp R : Uniform (fun i (x : Unit × α i) => f i x.2)).specialize i)
a (List.replicate m ()) ≤ m*(T+100*(V+m+1))+1 := by
induction m generalizing a with
| zero => simp only [List.replicate_zero,Realizer.foldTime,Nat.zero_mul,Nat.zero_add]; rfl
| succ m ih =>
have hv := hV 0 (by omega)
have hw := hV 1 (by omega)
have ht := hT 0 (by omega)
have hi := ih (f i a)
(fun j hj => by simpa only [Function.iterate_succ_apply] using hT (j+1) (by omega))
(fun j hj => by simpa only [Function.iterate_succ_apply] using hV (j+1) (by omega))
simp only [Function.iterate_zero_apply,Function.iterate_one] at hv hw ht
rw [List.replicate_succ,Realizer.foldTime]
change (snd.comp R).time i ((),a)+_+20*(volume (() :: List.replicate m ())+volume a+volume (f i a)+1) ≤ _
simp only [time_comp,time_snd,volume_pair,volume_unit,volume_cons,volume_replicate_unit,Function.comp_apply]
nlinarith
omit [∀ i, Coding (β i)] [∀ i, Coding (γ i)] in
theorem time_iterate_le {f : ∀ i, α i → α i} (R : Uniform f)
(i : I) (m : ℕ) (a : α i) (T V : ℕ)
(hT : ∀ j < m, R.time i ((f i)^[j] a) ≤ T)
(hV : ∀ j ≤ m, volume ((f i)^[j] a) ≤ V) :
R.iterate.time i (m,a) ≤ 10000*(m+1)*(T+V+m+1) := by
have hf := foldTime_iterate_le R i m a T V hT hV
have hv := hV 0 (Nat.zero_le _)
simp only [Function.iterate_zero_apply] at hv
simp only [iterate,time_congr,time_comp,onFst,time_pair,time_fst,time_snd,time_uniform,
Realizer.unroll,Realizer.time_reinterpret,Function.comp_apply,time_fold,volume_pair,
volume_nat,volume_replicate_unit]
nlinarith
end Uniform
end ThreeMachine.StackCompiler
end
end OAI
end
section
-- module Polynomial
namespace OAI
universe u1 u2
section
namespace ThreeMachine.StackCompiler
def Poly {I : Type u1} (size f : I → ℕ) (d : ℕ) : Prop :=
Majorized f (fun i => (size i+2)^d)
namespace Poly
variable {I : Type u2} {s f g : I → ℕ} {d e : ℕ}
theorem lift (h : Poly s f d) (hde : d ≤ e) : Poly s f e :=
h.trans (Majorized.pow_mono (fun _ => by omega) hde)
theorem of_le (h : ∀ i, f i ≤ g i) (hg : Poly s g d) : Poly s f d :=
(Majorized.of_le h).trans hg
theorem const (s : I → ℕ) (C : ℕ) : Poly s (fun _ => C) 0 :=
Majorized.const C (fun _ => by simp)
theorem base (s : I → ℕ) : Poly s (fun i => s i+2) 1 := by
simpa only [Poly,Nat.pow_one] using Majorized.refl (fun i => s i+2)
theorem size (s : I → ℕ) : Poly s s 1 :=
of_le (fun _ => by omega) (base s)
theorem add (hf : Poly s f d) (hg : Poly s g e) : Poly s (fun i => f i+g i) (max d e) :=
Majorized.add (hf.lift (le_max_left _ _)) (hg.lift (le_max_right _ _))
theorem mul (hf : Poly s f d) (hg : Poly s g e) : Poly s (fun i => f i*g i) (d+e) := by
simpa only [Poly,Nat.pow_add] using Majorized.mul hf hg
theorem pow (hf : Poly s f d) (k : ℕ) : Poly s (fun i => (f i)^k) (d*k) := by
simpa only [Poly,Nat.pow_mul] using Majorized.pow hf k
theorem max (hf : Poly s f d) (hg : Poly s g e) : Poly s (fun i => max (f i) (g i)) (max d e) :=
of_le (fun _ => by omega) (add hf hg)
end Poly
end ThreeMachine.StackCompiler
end
end OAI
end
section
-- module VolumeBounds
namespace OAI
universe u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16
section
namespace ThreeMachine.StackCompiler
namespace Realizer
variable {α : Type u1} [Coding α]
theorem time_iterate_le {f : α → α} (R : Realizer f) (m : ℕ) (a : α) (T V : ℕ)
(hT : ∀ j < m, R.time (f^[j] a) ≤ T)
(hV : ∀ j ≤ m, volume (f^[j] a) ≤ V) :
R.iterate.time (m,a) ≤ 10000*(m+1)*(T+V+m+1) := by
exact Uniform.time_iterate_le (R.uniform Unit) () m a T V hT hV
theorem time_add_le (a b : ℕ) : add.time (a,b) ≤ 10000000*(a+b+1)^2 := by
have h := time_iterate_le succ a b (200*(a+b+1)) (2*(a+b)+1)
(fun j hj => by rw [iterate_succ]; exact (time_succ_le _).trans (by omega))
(fun j hj => by rw [iterate_succ,volume_nat]; omega)
change succ.iterate.time (a,b) ≤ _
nlinarith
theorem time_sub_le (a b : ℕ) : sub.time (a,b) ≤ 10000000*(a+b+1)^2 := by
have h := time_iterate_le pred b a (2*a+3) (2*a+1)
(fun j _ => by rw [iterate_pred]; change volume (a-j)+2 ≤ _; rw [volume_nat]; omega)
(fun j _ => by rw [iterate_pred,volume_nat]; omega)
simp only [sub,time_congr,time_comp,swap,time_pair,time_fst,time_snd,volume_pair,volume_nat]
nlinarith
theorem time_le_le (a b : ℕ) : le.time (a,b) ≤ 1000000000*(a+b+1)^2 := by
have hs := time_sub_le a b
have hp := time_test_le (fun n : ℕ => decide (0 < n)) (by intro n; cases n <;> rfl) (a-b)
change positive.time (a-b) ≤ 10000*(volume (a-b)+1) at hp
simp only [volume_nat] at hp
have hn := time_not_le (decide (0 < a-b))
have hv := volume_bool (decide (0 < a-b))
simp only [le,time_congr,time_comp,isZero,volume_nat]
have hsq : a+b+1 ≤ (a+b+1)^2 := le_self_pow (by omega) (by decide)
omega
theorem time_eqNat_le (a b : ℕ) : eqNat.time (a,b) ≤ 10000000000*(a+b+1)^2 := by
have hl := time_le_le a b
have hr := time_le_le b a
have ha := time_and_le (decide (a ≤ b),decide (b ≤ a))
have hv := volume_bool (decide (a ≤ b))
have hw := volume_bool (decide (b ≤ a))
simp only [eqNat,time_congr,time_comp,time_pair,swap,time_fst,time_snd,volume_pair,volume_nat,
Function.comp_apply]
nlinarith
end Realizer
namespace Uniform
variable {I : Type u2} {α : I → Type u3} [∀ i, Coding (α i)]
end Uniform
end ThreeMachine.StackCompiler
end
section
namespace ThreeMachine.StackCompiler
@[simp] theorem volume_prod {α : Type u4} {β : Type u5} [Coding α] [Coding β] (x : α × β) :
volume x = volume x.1+volume x.2+1 := by cases x; exact volume_pair _ _
@[simp] theorem volume_state {n : ℕ} (x : Algorithm.State (Fin n)) :
volume x = volume x.left+volume x.middle+volume x.right+2 := by
change volume (x.left,(x.middle,x.right)) = _
simp only [volume_pair]; omega
@[simp] theorem volume_cardinal {n : ℕ} (x : Cardinal n) : volume x = 2*n+1 := volume_nat n
theorem volume_state_le {n : ℕ} (x : Algorithm.State (Fin n)) : volume x ≤ 12*(n+1)^2 := by
have h₁ := volume_finset_le x.left
have h₂ := volume_finset_le x.middle
have h₃ := volume_finset_le x.right
rw [volume_state]
have hpos : 1 ≤ (n+1)^2 := Nat.one_le_pow _ _ (by omega)
omega
namespace Poly
variable {I : Type u6} {s n f : I → ℕ} {d : ℕ}
theorem precomp (h : Poly s f d) {J : Type u7} (g : J → I) : Poly (s ∘ g) (f ∘ g) d := Majorized.precomp h g
theorem volumeNat (h : Poly s f d) : Poly s (fun i => volume (f i)) d := by
simp only [volume_nat]
(have polyH0 := Poly.const (s) (2); have polyH1 := Poly.mul polyH0 (h); have polyH2 := Poly.const (s) (1); have polyH3 := Poly.add polyH1 polyH2; exact Poly.lift polyH3 (by first | decide +kernel | omega))
theorem volumeBool (s : I → ℕ) (b : I → Bool) : Poly s (fun i => volume (b i)) 0 :=
of_le (fun i => volume_bool (b i)) (const s 3)
theorem volumeFin (hn : Poly s n d) (v : ∀ i, Fin (n i)) : Poly s (fun i => volume (v i)) d := by
apply of_le (g := fun i => 2*n i+1) (by intro i; rw [volume_fin]; have := (v i).isLt; omega)
(have polyH0 := Poly.const (s) (2); have polyH1 := Poly.mul polyH0 (hn); have polyH2 := Poly.const (s) (1); have polyH3 := Poly.add polyH1 polyH2; exact Poly.lift polyH3 (by first | decide +kernel | omega))
theorem volumeFinset (hn : Poly s n d) (v : ∀ i, Finset (Fin (n i))) :
Poly s (fun i => volume (v i)) (2*d) := by
apply of_le (fun i => volume_finset_le (v i))
(have polyH0 := Poly.const (s) (3); have polyH1 := Poly.const (s) (1); have polyH2 := Poly.add (hn) polyH1; have polyH3 := Poly.pow polyH2 (2); have polyH4 := Poly.mul polyH0 polyH3; exact Poly.lift polyH4 (by first | decide +kernel | omega))
theorem volumeState (hn : Poly s n d) (v : ∀ i, Algorithm.State (Fin (n i))) :
Poly s (fun i => volume (v i)) (2*d) := by
apply of_le (fun i => volume_state_le (v i))
(have polyH0 := Poly.const (s) (12); have polyH1 := Poly.const (s) (1); have polyH2 := Poly.add (hn) polyH1; have polyH3 := Poly.pow polyH2 (2); have polyH4 := Poly.mul polyH0 polyH3; exact Poly.lift polyH4 (by first | decide +kernel | omega))
variable {α : I → Type u8} {β : I → Type u9} [∀ i, Coding (α i)] [∀ i, Coding (β i)]
theorem volumeProd (f : ∀ i, α i × β i) {d e : ℕ}
(h₁ : Poly s (fun i => volume (f i).1) d) (h₂ : Poly s (fun i => volume (f i).2) e) :
Poly s (fun i => volume (f i)) (Max.max d e) := by
simp only [volume_prod]
(have polyH0 := Poly.add (h₁) (h₂); have polyH1 := Poly.const (s) (1); have polyH2 := Poly.add polyH0 polyH1; exact Poly.lift polyH2 (by first | decide +kernel | omega))
omit [∀ i, Coding (β i)] in
theorem volumeList {xs : ∀ i, List (α i)} {V : I → ℕ} {d e : ℕ}
(hl : Poly s (fun i => (xs i).length) d) (hV : Poly s V e)
(hv : ∀ i, ∀ a ∈ xs i, volume a ≤ V i) :
Poly s (fun i => volume (xs i)) (d+e) := by
apply of_le (fun i => volume_list_le (xs i) (V i) (hv i))
(have polyH0 := Poly.const (s) (1); have polyH1 := Poly.add (hV) polyH0; have polyH2 := Poly.mul (hl) polyH1; have polyH3 := Poly.add polyH2 polyH0; exact Poly.lift polyH3 (by first | decide +kernel | omega))
end Poly
end ThreeMachine.StackCompiler
end
section
namespace ThreeMachine.StackCompiler
@[simp] theorem volume_ofFn {α : Type u10} [Coding α] {n : ℕ} (f : Fin n → α) :
volume (List.ofFn f) = volume f := rfl
@[simp] theorem volume_sort {n : ℕ} (s : Finset (Fin n)) : volume (s.sort (· ≤ ·)) = volume s := rfl
namespace Uniform
variable {I : Type u12} {α : I → Type u13} {β : I → Type u14} [∀ i, Coding (α i)] [∀ i, Coding (β i)]
@[simp] theorem time_functionListAny (d : I → ℕ) (i : I) (f : Fin (d i) → α i) :
(functionListAny d).time i f = volume f+2 := rfl
@[simp] theorem time_finValue (d : I → ℕ) (i : I) (v : Fin (d i)) :
(finValue d).time i v = volume v+2 := rfl
@[simp] theorem time_reindex {f : ∀ i, α i → β i} (R : Uniform f) {J : Type u16}
(φ : J → I) (j : J) (x : α (φ j)) : (R.reindex φ).time j x = R.time (φ j) x := rfl
end Uniform
end ThreeMachine.StackCompiler
end
section
namespace ThreeMachine.StackCompiler
end ThreeMachine.StackCompiler
end
end OAI
end
section
-- module PolynomialLoops
namespace OAI
universe u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16 u17 u18 u19 u20 u21 u22 u23 u24 u25 u26 u27
section
namespace ThreeMachine.StackCompiler
namespace Poly
variable {I : Type u1} {J : Type u2} {s : J → ℕ}
variable {α : I → Type u3} {β : I → Type u4} {γ : I → Type u5} [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
variable (idx : J → I) (xs : ∀ j, List (α (idx j))) (e : ∀ j, γ (idx j))
abbrev Pool := Σ j, {a : α (idx j) // a ∈ xs j}
theorem reparam {K : Type u6} {u f : K → ℕ} {d r : ℕ}
(h : Poly u f d) (g : J → K) (hs : Poly s (fun j => u (g j)) r) :
Poly s (fun j => f (g j)) (d*r) := by
obtain ⟨C,hC⟩ := h
apply of_le (fun j => hC (g j))
have hN : Poly s (fun j => u (g j)+2) r := by
simpa only [Nat.max_zero] using hs.add (const s 2)
simpa only [Nat.zero_add,Nat.mul_comm] using (const s C).mul (hN.pow d)
theorem powerBase (s : J → ℕ) (C d : ℕ) : Poly s (fun j => C*(s j+2)^d) d := by
(have polyH0 := Poly.const (s) (C); have polyH1 := Poly.base (s); have polyH2 := Poly.pow polyH1 (d); have polyH3 := Poly.mul polyH0 polyH2; exact Poly.lift polyH3 (by first | decide +kernel | omega))
theorem anyTime {p : ∀ i, α i × γ i → Bool} (P : Uniform p) {l t vx ve : ℕ}
(hl : Poly s (fun j => (xs j).length) l)
(ht : Poly (fun q : Pool idx xs => s q.1)
(fun q => P.time (idx q.1) (q.2.1,e q.1)) t)
(hx : Poly s (fun j => volume (xs j)) vx)
(he : Poly s (fun j => volume (e j)) ve) :
Poly s (fun j => P.any.time (idx j) (xs j,e j)) (l+Max.max t (Max.max vx ve)) := by
obtain ⟨C,hC⟩ := ht
have hT := powerBase s C t
apply of_le (fun j => Uniform.time_any P (idx j) (xs j) (e j)
(C*(s j+2)^t) (fun a ha => hC ⟨j,⟨a,ha⟩⟩))
(have polyH0 := Poly.const (s) (10000000); have polyH1 := Poly.const (s) (1); have polyH2 := Poly.add (hl) polyH1; have polyH3 := Poly.mul polyH0 polyH2; have polyH4 := Poly.add (hT) (hx); have polyH5 := Poly.add polyH4 (he); have polyH6 := Poly.add polyH5 polyH1; have polyH7 := Poly.mul polyH3 polyH6; exact Poly.lift polyH7 (by first | decide +kernel | omega))
theorem allTime {p : ∀ i, α i × γ i → Bool} (P : Uniform p) {l t vx ve : ℕ}
(hl : Poly s (fun j => (xs j).length) l)
(ht : Poly (fun q : Pool idx xs => s q.1)
(fun q => P.time (idx q.1) (q.2.1,e q.1)) t)
(hx : Poly s (fun j => volume (xs j)) vx)
(he : Poly s (fun j => volume (e j)) ve) :
Poly s (fun j => P.all.time (idx j) (xs j,e j)) (l+Max.max t (Max.max vx ve)) := by
obtain ⟨C,hC⟩ := ht
have hT := powerBase s C t
apply of_le (fun j => Uniform.time_all P (idx j) (xs j) (e j)
(C*(s j+2)^t) (fun a ha => hC ⟨j,⟨a,ha⟩⟩))
(have polyH0 := Poly.const (s) (1000000000000); have polyH1 := Poly.const (s) (1); have polyH2 := Poly.add (hl) polyH1; have polyH3 := Poly.mul polyH0 polyH2; have polyH4 := Poly.add (hT) (hx); have polyH5 := Poly.add polyH4 (he); have polyH6 := Poly.add polyH5 polyH1; have polyH7 := Poly.mul polyH3 polyH6; exact Poly.lift polyH7 (by first | decide +kernel | omega))
end Poly
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler
namespace Poly
variable {J : Type u7} {s : J → ℕ} {d : ℕ}
theorem finsetCard {n : J → ℕ} (hn : Poly s n d) (a : ∀ j, Finset (Fin (n j))) :
Poly s (fun j => (a j).card) d :=
of_le (fun j => by simpa only [Fintype.card_fin] using Finset.card_le_univ (a j)) hn
variable {α : J → Type u8} {β : J → Type u9} [∀ j, Coding (α j)] [∀ j, Coding (β j)]
omit [∀ j, Coding (β j)] in
theorem volumePool (xs : ∀ j, List (α j)) (h : Poly s (fun j => volume (xs j)) d) :
Poly (fun q : Pool _root_.id xs => s q.1) (fun q => volume q.2.1) d :=
of_le (fun q => volume_mem_le q.2.2) (h.precomp Sigma.fst)
end Poly
end ThreeMachine.StackCompiler
namespace ThreeMachine.StackCompiler.Poly
variable {J : Type u10} {s n : J → ℕ} {d : ℕ}
theorem lengthSort (a : ∀ j, Finset (Fin (n j)))
(h : Poly s (fun j => (a j).card) d) :
Poly s (fun j => ((a j).sort (· ≤ ·)).length) d := by simpa only [Finset.length_sort] using h
end ThreeMachine.StackCompiler.Poly
namespace ThreeMachine.StackCompiler.Poly
variable {I : Type u12} {J : Type u13} {α : I → Type u14} {β : I → Type u15} [∀ i, Coding (α i)] [∀ i, Coding (β i)]
end ThreeMachine.StackCompiler.Poly
namespace ThreeMachine.StackCompiler.Poly
variable {J : Type u16} {s n : J → ℕ} {d v : ℕ}
def FinPool (n : J → ℕ) := Σ j, Fin (n j)
theorem iteNat (p : J → Prop) [∀ j, Decidable (p j)] {f g : J → ℕ} {d e : ℕ}
(hf : Poly s f d) (hg : Poly s g e) : Poly s (fun j => if p j then f j else g j) (Max.max d e) :=
of_le (g := fun j => Max.max (f j) (g j)) (fun j => by split <;> omega) (hf.max hg)
end ThreeMachine.StackCompiler.Poly
namespace ThreeMachine.StackCompiler.Poly
variable {I : Type u18} {J : Type u19} {s : J → ℕ}
variable {α : I → Type u20} {β : I → Type u21} {γ : I → Type u22} [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
variable (idx : J → I) (xs : ∀ j, List (α (idx j))) (e : ∀ j, γ (idx j))
end ThreeMachine.StackCompiler.Poly
namespace ThreeMachine.StackCompiler.Poly
variable {J : Type u23} {s : J → ℕ} {d e : ℕ} {α : J → Type u24} {β : J → Type u25}
variable [∀ j, Coding (α j)] [∀ j, Coding (β j)]
end ThreeMachine.StackCompiler.Poly
namespace ThreeMachine.StackCompiler.Poly
variable {J : Type u26} {s : J → ℕ} {α : J → Type u27} [∀ j, Coding (α j)]
abbrev ListPool (xs : ∀ j, List (α j)) := Σ j, {a : α j // a ∈ xs j}
theorem listVolume (xs : ∀ j, List (α j)) {l v : ℕ}
(hl : Poly s (fun j => (xs j).length) l)
(hv : Poly (fun q : ListPool xs => s q.1) (fun q => volume q.2.1) v) :
Poly s (fun j => volume (xs j)) (l+v) := by
obtain ⟨C,hC⟩ := hv
exact volumeList hl (powerBase s C v) (fun j a ha => hC ⟨j,⟨a,ha⟩⟩)
end ThreeMachine.StackCompiler.Poly
end
end OAI
end
section
-- module PolynomialLists
namespace OAI
universe u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16
section
namespace ThreeMachine.StackCompiler
@[simp] theorem volume_block {n : ℕ} (b : Algorithm.Block (Fin n)) :
volume b = volume b.length+volume b.time+1 := by
change volume (b.length,b.time) = _
rw [volume_pair]
namespace Poly
variable {J : Type u1} {s n : J → ℕ} {d e : ℕ}
variable {α : J → Type u2} {β : J → Type u3} [∀ j, Coding (α j)] [∀ j, Coding (β j)]
omit [∀ j, Coding (β j)] in
theorem volumeOption (o : ∀ j, Option (α j)) {v : J → ℕ}
(h : Poly s v d) (hv : ∀ j, ∀ a ∈ o j, volume a ≤ v j) : Poly s (fun j => volume (o j)) d := by
apply of_le (fun j => volume_option_le (o j) (v j) (hv j))
(have polyH0 := Poly.const (s) (2); have polyH1 := Poly.add (h) polyH0; exact Poly.lift polyH1 (by first | decide +kernel | omega))
end Poly
end ThreeMachine.StackCompiler
end
section
namespace ThreeMachine.StackCompiler.Poly
variable {I : Type u4} {J : Type u5} {s : J → ℕ}
variable {α : I → Type u6} {β : I → Type u7} {γ : I → Type u8} [∀ i, Coding (α i)] [∀ i, Coding (β i)] [∀ i, Coding (γ i)]
variable (idx : J → I) (xs : ∀ j, List (α (idx j))) (e : ∀ j, γ (idx j))
variable (o : ∀ j, Option (α (idx j)))
theorem optionMapTime {f : ∀ i, α i × γ i → β i} (R : Uniform f) {t vo ve v : ℕ}
(ht : Poly (fun p : Pool idx (fun j => (o j).toList) => s p.1)
(fun p => R.time (idx p.1) (p.2.1,e p.1)) t)
(ho : Poly s (fun j => volume (o j)) vo)
(he : Poly s (fun j => volume (e j)) ve)
(hv : Poly (fun p : Pool idx (fun j => (o j).toList) => s p.1)
(fun p => volume (f (idx p.1) (p.2.1,e p.1))) v) :
Poly s (fun j => R.optionMap.time (idx j) (o j,e j)) (Max.max t (Max.max vo (Max.max ve v))) := by
obtain ⟨C,hC⟩ := ht
obtain ⟨D,hD⟩ := hv
have hT := powerBase s C t
have hV := powerBase s D v
apply of_le (fun j => Uniform.time_optionMap R (idx j) (o j) (e j)
(C*(s j+2)^t) (D*(s j+2)^v) (fun a ha => hC ⟨j,⟨a,by simpa using ha⟩⟩)
(fun a ha => hD ⟨j,⟨a,by simpa using ha⟩⟩))
(have polyH0 := Poly.const (s) (1000000); have polyH1 := Poly.add (hT) (ho); have polyH2 := Poly.add polyH1 (he); have polyH3 := Poly.add polyH2 (hV); have polyH4 := Poly.const (s) (1); have polyH5 := Poly.add polyH3 polyH4; have polyH6 := Poly.mul polyH0 polyH5; exact Poly.lift polyH6 (by first | decide +kernel | omega))
end ThreeMachine.StackCompiler.Poly
namespace ThreeMachine.StackCompiler.Poly
variable {J : Type u9} {s : J → ℕ} {d e : ℕ} {α : J → Type u10} {β : J → Type u11}
variable [∀ j, Coding (α j)] [∀ j, Coding (β j)]
omit [∀ j, Coding (β j)] in
theorem volumeIte (p : J → Prop) [∀ j, Decidable (p j)] (a b : ∀ j, α j)
(ha : Poly s (fun j => volume (a j)) d) (hb : Poly s (fun j => volume (b j)) e) :
Poly s (fun j => volume (if p j then a j else b j)) (Max.max d e) := by
convert iteNat p ha hb using 1
funext j; split <;> rfl
omit [∀ j, Coding (α j)] in
theorem volumeOptionMap (f : ∀ j, α j → β j) (o : ∀ j, Option (α j))
(h : Poly (fun p : ListPool (fun j => (o j).toList) => s p.1)
(fun p => volume (f p.1 p.2.1)) d) : Poly s (fun j => volume ((o j).map (f j))) d := by
obtain ⟨C,hC⟩ := h
apply volumeOption _ (powerBase s C d)
intro j b hb
cases ho : o j with
| none => simp [ho] at hb
| some a =>
have he : f j a = b := by simpa [ho] using hb
subst b
exact hC ⟨j,⟨a,by simp [ho]⟩⟩
end ThreeMachine.StackCompiler.Poly
namespace ThreeMachine.StackCompiler.Poly
variable {J : Type u12} {s : J → ℕ} {d : ℕ} {K V : J → Type}
variable [∀ j, Coding (K j)] [∀ j, Coding (V j)] [∀ j, DecidableEq (K j)]
end ThreeMachine.StackCompiler.Poly
namespace ThreeMachine.StackCompiler.Poly
variable {J : Type u13} {s : J → ℕ} {d : ℕ} {α : J → Type u14} [∀ j, Coding (α j)]
theorem volumeOptionToList (o : ∀ j, Option (α j))
(h : Poly s (fun j => volume (o j)) d) :
Poly s (fun j => volume (o j).toList) d := by
simpa only [volume_optionToList] using h
end ThreeMachine.StackCompiler.Poly
end
section
namespace ThreeMachine.StackCompiler.Poly
variable {J : Type u15} {s : J → ℕ} {d e : ℕ} {α : J → Type u16}
theorem lengthCons (a : ∀ j, α j) (xs : ∀ j, List (α j))
(h : Poly s (fun j => (xs j).length) d) :
Poly s (fun j => (a j :: xs j).length) d := by
simp only [List.length_cons]; (have polyH0 := Poly.const (s) (1); have polyH1 := Poly.add (h) polyH0; exact Poly.lift polyH1 (by first | decide +kernel | omega))
end ThreeMachine.StackCompiler.Poly
end
end OAI
end