Research source · Plain text

BoundedActionWindow.lean

formalizations/frontier-derivative/FrontierDerivative/BoundedActionWindow.lean

248 lines. Source is displayed for inspection; it is not executed by this page.

File fingerprint

SHA-256: a4b62660ddae1f17f0cf5366720535e7e883d25288ba5c278457319f34154255

import FrontierDerivative.LastActionRefinement

/-!
# Canonical bounded hidden-action windows

Successful traces are defined on the original partial visible machine. Their
last `k` hidden actions, newest first, form a canonical finite-shape control
refinement. If each such window class carries at most one stack per original
control, the refinement is control-functional and reaches the existing
compiler.
-/

namespace FrontierDerivative.BoundedActionWindow

open FiniteRefinement
open FiniteReindexing

universe uΓ

variable {Input Q : Type} {Γ : Type uΓ}

/-! ## Bounded action memory -/

/-- A newest-first list of at most `k` hidden visible actions. -/
def ActionWindow (k : Nat) := { actions : List VisibleAction // actions.length ≤ k }

/-- The action window at the empty-word boundary. -/
def emptyWindow (k : Nat) : ActionWindow k := ⟨[], Nat.zero_le k⟩

/-- Record the current action at the front and forget everything beyond the
fixed depth. -/
def pushWindow (k : Nat) (action : VisibleAction)
    (memory : ActionWindow k) : ActionWindow k :=
  ⟨(action :: memory.1).take k, by
    rw [List.length_take]
    exact Nat.min_le_left _ _⟩

/-- The exact bounded window of a chronological action trace. -/
def windowOf (k : Nat) (actions : List VisibleAction) : ActionWindow k :=
  actions.foldl (fun memory action => pushWindow k action memory)
    (emptyWindow k)

theorem windowOf_append (k : Nat) (actions : List VisibleAction)
    (action : VisibleAction) :
    windowOf k (actions ++ [action]) =
      pushWindow k action (windowOf k actions) := by
  simp [windowOf]

theorem pushWindow_zero (action : VisibleAction) (memory : ActionWindow 0) :
    pushWindow 0 action memory = emptyWindow 0 := by
  apply Subtype.ext
  rfl

theorem windowOf_zero (actions : List VisibleAction) :
    windowOf 0 actions = emptyWindow 0 := by
  apply Subtype.ext
  rcases windowOf 0 actions with ⟨memory, hmemory⟩
  dsimp
  cases memory with
  | nil => rfl
  | cons action rest => simp at hmemory

/-! ## Original traced semantics -/

/-- One successful hidden action per observed input round, retained in
chronological order. This relation belongs to the original machine. -/
inductive TracedReachable (V : PartialVisible.Machine Input Q Γ) :
    List Input → List VisibleAction → PartialVisible.Config Q Γ → Prop where
  | init : TracedReachable V [] [] V.initConfig
  | step {w : List Input} {actions : List VisibleAction}
      {c : PartialVisible.Config Q Γ} (a : Input) (action : VisibleAction)
      {c' : PartialVisible.Config Q Γ} :
      TracedReachable V w actions c →
      V.apply a action c = some c' →
      TracedReachable V (w ++ [a]) (actions ++ [action]) c'

/-- The original successful frontier classified by its exact last-`k` action
window. The refined machine does not occur in this definition. -/
def WindowFrontier (V : PartialVisible.Machine Input Q Γ) (k : Nat)
    (w : List Input) (memory : ActionWindow k) (q : Q) (z : List Γ) : Prop :=
  ∃ actions,
    TracedReachable V w actions ⟨q, z⟩ ∧
      windowOf k actions = memory

/-- For one fixed input prefix, target control, and bounded hidden-action
window, there is at most one resulting concrete stack. -/
def WindowSeparated (V : PartialVisible.Machine Input Q Γ) (k : Nat) : Prop :=
  ∀ w memory q z₁ z₂,
    WindowFrontier V k w memory q z₁ →
    WindowFrontier V k w memory q z₂ →
    z₁ = z₂

/-! ## Canonical machine -/

/-- Refine control by the bounded window of the successful hidden actions seen
so far. -/
def rememberWindow (V : PartialVisible.Machine Input Q Γ) (k : Nat) :
    PartialVisible.Machine Input (Q × ActionWindow k) Γ where
  call := fun state a =>
    (V.call state.1 a).map fun next =>
      ((next.1, pushWindow k .call state.2), next.2)
  ret := fun state a top =>
    (V.ret state.1 a top).map fun q =>
      (q, pushWindow k .ret state.2)
  localStep := fun state a =>
    (V.localStep state.1 a).map fun q =>
      (q, pushWindow k .local state.2)
  init := (V.init, emptyWindow k)
  accept := fun state => V.accept state.1

/-- A refined command is exactly the original same-round command, and its
target memory is exactly the current action pushed into the old window. -/
theorem rememberWindow_apply_iff
    (V : PartialVisible.Machine Input Q Γ) (k : Nat)
    (a : Input) (action : VisibleAction) (q q' : Q)
    (memory memory' : ActionWindow k) (z z' : List Γ) :
    (rememberWindow V k).apply a action ⟨(q, memory), z⟩ =
        some ⟨(q', memory'), z'⟩ ↔
      V.apply a action ⟨q, z⟩ = some ⟨q', z'⟩ ∧
        memory' = pushWindow k action memory := by
  cases action with
  | call =>
      cases hcommand : V.call q a with
      | none => simp [rememberWindow, PartialVisible.Machine.apply, hcommand]
      | some next =>
          rcases next with ⟨target, symbol⟩
          simp [rememberWindow, PartialVisible.Machine.apply, hcommand,
            eq_comm, and_assoc, and_left_comm, and_comm]
  | ret =>
      cases hcommand : V.ret q a z.head? with
      | none => simp [rememberWindow, PartialVisible.Machine.apply, hcommand]
      | some target =>
          simp [rememberWindow, PartialVisible.Machine.apply, hcommand,
            eq_comm, and_assoc, and_left_comm, and_comm]
  | «local» =>
      cases hcommand : V.localStep q a with
      | none => simp [rememberWindow, PartialVisible.Machine.apply, hcommand]
      | some target =>
          simp [rememberWindow, PartialVisible.Machine.apply, hcommand,
            eq_comm, and_assoc, and_left_comm, and_comm]

/-- Forgetting the bounded window is a lawful same-action, same-stack
refinement. -/
def rememberWindowRefinement (V : PartialVisible.Machine Input Q Γ) (k : Nat) :
    Refinement V (rememberWindow V k) where
  erase := Prod.fst
  init_eq := rfl
  accept_eq := by intro; rfl
  apply_sound := by
    intro a action state z state' z' h
    rcases state with ⟨q, memory⟩
    rcases state' with ⟨q', memory'⟩
    exact ((rememberWindow_apply_iff V k a action q q' memory memory' z z').1 h).1
  apply_complete := by
    intro a action state z q' z' h
    rcases state with ⟨q, memory⟩
    refine ⟨(q', pushWindow k action memory), ?_, rfl⟩
    exact (rememberWindow_apply_iff V k a action q q' memory
      (pushWindow k action memory) z z').2 ⟨h, rfl⟩

/-! ## Exact trace translations -/

/-- Every original successful trace lifts to the refined run with exactly its
folded action window. -/
theorem traced_to_remembered (V : PartialVisible.Machine Input Q Γ) (k : Nat)
    {w : List Input} {actions : List VisibleAction}
    {c : PartialVisible.Config Q Γ}
    (h : TracedReachable V w actions c) :
    (rememberWindow V k).TaggedReachable w
      ⟨(c.ctrl, windowOf k actions), c.stack⟩ := by
  induction h with
  | init => exact PartialVisible.Machine.TaggedReachable.init
  | step a action hprev happly ih =>
      apply PartialVisible.Machine.TaggedReachable.step a action ih
      rw [windowOf_append]
      exact (rememberWindow_apply_iff V k a action _ _ _ _ _ _).2
        ⟨happly, rfl⟩

/-- Every refined successful run erases to an original chronological trace,
and the stored memory is exactly that trace's bounded window. -/
theorem remembered_to_traced (V : PartialVisible.Machine Input Q Γ) (k : Nat)
    {w : List Input} {state : PartialVisible.Config (Q × ActionWindow k) Γ}
    (h : (rememberWindow V k).TaggedReachable w state) :
    ∃ actions,
      TracedReachable V w actions ⟨state.ctrl.1, state.stack⟩ ∧
        windowOf k actions = state.ctrl.2 := by
  induction h with
  | init => exact ⟨[], TracedReachable.init, rfl⟩
  | @step w state a action state' hprev happly ih =>
      rcases state with ⟨⟨q, memory⟩, z⟩
      rcases state' with ⟨⟨q', memory'⟩, z'⟩
      rcases ih with ⟨actions, htrace, hmemory⟩
      rcases (rememberWindow_apply_iff V k a action q q' memory memory' z z').1
        happly with ⟨horiginal, htarget⟩
      refine ⟨actions ++ [action],
        TracedReachable.step a action htrace horiginal, ?_⟩
      rw [windowOf_append, hmemory]
      exact htarget.symm

/-- The refined frontier is exactly the original traced frontier classified by
its stored action window, for every prefix including epsilon. -/
theorem frontier_window_iff (V : PartialVisible.Machine Input Q Γ) (k : Nat)
    (w : List Input) (memory : ActionWindow k) (q : Q) (z : List Γ) :
    (rememberWindow V k).Frontier w (q, memory) z ↔
      WindowFrontier V k w memory q z := by
  rw [PartialVisible.Machine.frontier_iff_tagged]
  constructor
  · intro h
    exact remembered_to_traced V k h
  · rintro ⟨actions, htrace, hmemory⟩
    have hrefined := traced_to_remembered V k htrace
    simpa [hmemory] using hrefined

/-! ## Separation and compilation -/

/-- Window separation on the original traced semantics makes the canonical
refined frontier control-functional. -/
theorem rememberWindow_controlFunctional
    (V : PartialVisible.Machine Input Q Γ) (k : Nat)
    (hsep : WindowSeparated V k) :
    ControlFunctionalOn (rememberWindow V k) := by
  intro w state z₁ z₂ h₁ h₂
  rcases state with ⟨q, memory⟩
  exact hsep w memory q z₁ z₂
    ((frontier_window_iff V k w memory q z₁).1 h₁)
    ((frontier_window_iff V k w memory q z₂).1 h₂)

/-- A supplied enumeration of the full bounded-window control carrier compiles
the original forgotten-action projection. -/
theorem compiled_decides_window {s : Nat}
    (V : PartialVisible.Machine Input Q Γ) (k : Nat)
    (hsep : WindowSeparated V k)
    (e : ControlEquiv (Q × ActionWindow k) (Fin s))
    (w : List Input) :
    (RootSharingMachine.compile
      (ControlFunctional.executor (rename (rememberWindow V k) e))).decides w =
        true ↔ V.Accepts w := by
  exact compiled_decides_original_via_equiv (rememberWindowRefinement V k) e
    (rememberWindow_controlFunctional V k hsep) w

#check TracedReachable
#check WindowFrontier
#check rememberWindowRefinement
#check frontier_window_iff
#check rememberWindow_controlFunctional
#check compiled_decides_window

end FrontierDerivative.BoundedActionWindow