Theory AlphabetEnlargement_Defs

theory AlphabetEnlargement_Defs
  imports "Multitape_TM_Substrate.Multitape_Substrate"
begin

section ‹Alphabet enlargement›

text ‹Setup for the ‹alphabet_enlarge› combinator:
  substrate selectors, stage-bookkeeping types, offset and
  block helpers, encoder / decoder, encoder-canonicity
  predicates, per-substep transition relations, the
  ‹alphabet_enlarge› combinator itself, the
  ‹ae_simulates› relation, and the eight mid-stage
  invariants ‹ae_inv_ss1› through ‹ae_inv_ss8›,
  plus the upstream structural lemmas, the encoder-roundtrip
  chain, and the validation-phase chain culminating in
  ‹ae_validation_steps_bound›.

  The forward-simulation chain that consumes the validation
  result, and the top-level theorems
  ‹alphabet_enlarge_wf›,
  ‹alphabet_enlarge_language›, and
  ‹alphabet_enlarge_time›, follow further on in this
  chapter.›

text ‹Substrate selectors (‹bl_tm›, ‹le_tm›, ‹delta_tm›,
  ‹s_tm›, ‹t_tm›, ‹r_tm›, ‹Sigma_tm›, ‹mt_tape›) live in
  the ‹Multitape_Substrate› theory alongside the functional substrate
  layer; they're imported transitively.›

subsection ‹Stage bookkeeping types›

text ‹Substep counter / phase indicator for ‹M'›'s state machine.

  Constructors ‹VFwd› / ‹VFwdPad› / ‹VRet› mark the
  validation phase: forward scan (no padded block seen yet),
  forward scan after a trailing-padded block has been
  observed, and return scan back to the first input block.

  Constructors ‹SS1› … ‹SS8› mark the 8-substep simulation
  stage of Hopcroft--Ullman
  cite‹‹Theorem 12.3› in "Hopcroft1979:introduction"›; ‹SSn›
  corresponds to the spec's "substep ‹n›".›

datatype substep_idx =
    VFwd | VFwdPad | VRet
  | SS1 | SS2 | SS3 | SS4 | SS5 | SS6 | SS7 | SS8

instance substep_idx :: finite
proof (intro_classes)
  have "(UNIV :: substep_idx set) ⊆
          {VFwd, VFwdPad, VRet,
           SS1, SS2, SS3, SS4, SS5, SS6, SS7, SS8}"
    using substep_idx.exhaust by blast
  thus "finite (UNIV :: substep_idx set)"
    using finite_subset by auto
qed

text ‹Per-tape destination indicator: which buffer slot now holds
  the home block of ‹M›'s simulated head, after the compute
  substep (the 4th component of ‹stage›).
  The compute substep sets this; the write-back phase consumes it
  to choose between move-sequence variants
  (`L,R,R,N` / `L,R,R,L` / `R,L,L,N` for steady-state stages).›

datatype ae_dest = AE_Left | AE_Home | AE_Right

instance ae_dest :: finite
proof (intro_classes)
  have "(UNIV :: ae_dest set) ⊆ {AE_Left, AE_Home, AE_Right}"
    using ae_dest.exhaust by blast
  thus "finite (UNIV :: ae_dest set)"
    using finite_subset by auto
qed

text ‹Stage bookkeeping carried in the output machine's state set:
  per-tape within-block offset (‹nat ⇒ 'c›), per-tape three-block
  buffer (left, home, right), per-tape destination indicator
  (‹AE_Left› / ‹AE_Home› / ‹AE_Right›), and the substep counter
  within the current 8-substep stage.›

type_synonym ('a, 'c) ae_stage =
  "(nat ⇒ 'c)
   × (nat ⇒ ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a))
   × (nat ⇒ ae_dest)
   × substep_idx"

subsection ‹Offset arithmetic on ‹'c››

text ‹The compute substep tracks a simulated head position by an
  offset within a 3-block buffer; advancing by ‹L› / ‹R›
  requires partial successor / predecessor on ‹'c›.  We use the
  canonical enumeration provided by the ‹enum› class.›

definition c_idx :: "'c :: enum ⇒ nat" where
  "c_idx x = (THE i. i < length (enum_class.enum :: 'c list)
                     ∧ (enum_class.enum :: 'c list) ! i = x)"

definition c_first :: "'c :: enum" where
  "c_first = (enum_class.enum :: 'c list) ! 0"

definition c_last :: "'c :: enum" where
  "c_last = (enum_class.enum :: 'c list)
              ! (length (enum_class.enum :: 'c list) - 1)"

definition c_succ :: "'c :: enum ⇒ 'c option" where
  "c_succ x =
     (let xs = enum_class.enum :: 'c list; i = c_idx x in
        if Suc i < length xs then Some (xs ! Suc i) else None)"

definition c_pred :: "'c :: enum ⇒ 'c option" where
  "c_pred x =
     (let xs = enum_class.enum :: 'c list; i = c_idx x in
        if i = 0 then None else Some (xs ! (i - 1)))"

subsection ‹Block-encoding helpers›

text ‹The constant LE-block: a block whose every cell holds
  ‹M›'s left-endmarker symbol.  Used as ‹M'›'s left endmarker.
  Compatible with the substrate's ‹δLE› invariant: any read of
  this block tests ‹le› at every cell, so the
  ‹a k = LE ⟹ a' k = LE ∧ d k ∈ {N, R}› obligation lifts
  pointwise from ‹M›'s.›

definition LE_block :: "'a ⇒ ('c :: enum ⇒ 'a)" where
  "LE_block le = (λ_. le)"

text ‹The constant blank-block: a block whose every cell holds
  ‹M›'s blank symbol.  Used as ‹M'›'s blank, and also as the
  semantic placeholder for ‹buf.left› in LE-stages.›

definition bl_block :: "'a ⇒ ('c :: enum ⇒ 'a)" where
  "bl_block bl = (λ_. bl)"

subsection ‹Encoder›

text ‹Encoding an input word as a list of ‹c›-blocks,
  padding the final block with the substrate's blank symbol if the
  input length is not a multiple of ‹c›.

  The grouping factor ‹c = card (UNIV :: 'c set)› is determined at
  the type level.  Block ‹i› (for ‹i < ⌈length w / c⌉›) is
  the function ‹λx. if i ⋅ c + c_idx x < length w then w ! (i ⋅ c
  + c_idx x) else bl›; the output list has length
  ‹⌈length w / c⌉›, computed in nat arithmetic as
  ‹(length w + c - 1) div c›.›

definition encode_input ::
  "'a ⇒ 'a list ⇒ (('c :: enum) ⇒ 'a) list" where
  "encode_input bl w =
     (let c = card (UNIV :: 'c set) in
        map (λi. (λx. let j = i * c + c_idx x in
                          if j < length w then w ! j else bl))
            [0 ..< (length w + c - 1) div c])"

subsection ‹Decoder›

text ‹Decoder: extract ‹M›-symbols from a list of blocks by
  taking each block's ‹bl›-free prefix under the canonical
  ‹'c›-enumeration.  For pure blocks this yields all ‹c›
  cells; for trailing-padded blocks it yields the non-blank
  prefix; for non-canonical blocks (blank-then-non-blank
  pattern) it yields the leading non-blank prefix only — but
  the validation phase rejects these before decoding is invoked.
  Inverse to ‹encode_input› on the encoder image; cited by the
  forward direction of
  ‹ae_validation_canonical_iff_encoder_image›.›

definition ae_decode_block :: "'a ⇒ ('c :: enum ⇒ 'a) ⇒ 'a list" where
  "ae_decode_block bl f =
     takeWhile (λa. a ≠ bl) (map f (enum_class.enum :: 'c list))"

definition ae_decode_input :: "'a ⇒ (('c :: enum) ⇒ 'a) list ⇒ 'a list" where
  "ae_decode_input bl w = concat (map (ae_decode_block bl) w)"

subsection ‹Initial stage›

text ‹Initial within-block offset.  Every tape's offset starts at a
  canonical element of ‹'c› (treated as the within-block position
  of ‹M›'s left endmarker on each tape).  The specific element is
  underspecified at this level; the simulation argument (§30.4)
  fixes a canonical ‹0›-offset matching ‹M›'s initial head
  position.›

definition init_offset :: "nat ⇒ ('c :: enum)" where
  "init_offset = (λ_. SOME x. True)"

text ‹Initial buffer.  Every tape starts with three constant
  ‹LE›-blocks: at ‹M'›'s position 0 the home block is the
  left-endmarker block, and the buffer phase has not yet executed
  on the surrounding cells; the SS1‹→›SS4 buffer phase
  refills the slots from actual tape contents at the start of
  every stage.›

definition init_buffer ::
  "'a ⇒ (nat ⇒ (('c :: enum ⇒ 'a)
                  × ('c ⇒ 'a)
                  × ('c ⇒ 'a)))" where
  "init_buffer le = (λ_. (LE_block le, LE_block le, LE_block le))"

text ‹Initial destination indicator: every tape starts with
  ‹AE_Home› (the indicator is meaningful only after the compute
  substep sets it; the initial value is canonical).›

definition init_dest :: "nat ⇒ ae_dest" where
  "init_dest = (λ_. AE_Home)"

text ‹Initial stage: zero offset, all-‹LE› buffers, dest = home,
  substep counter ‹SS1›.›

definition init_stage ::
  "'a ⇒ ('a, 'c :: enum) ae_stage" where
  "init_stage le = (init_offset, init_buffer le, init_dest, VFwd)"

subsection ‹Encoder-canonicity predicates›

text ‹A block is ‹pure› if every cell is non-blank.  In the
  encoder image, every block except possibly the last has
  this form (every cell is from the original input).›

definition is_pure_block ::
  "'a ⇒ ('c :: enum ⇒ 'a) ⇒ bool" where
  "is_pure_block bl f = (∀x. f x ≠ bl)"

text ‹A block is ‹trailing-padded› if there is a non-empty,
  proper prefix (under the canonical ‹'c›-enumeration) of
  non-blank cells, and the remaining cells are all blank.  In the
  encoder image, the last block has this form when the
  input length is not a multiple of ‹c›.›

definition is_padded_block ::
  "'a ⇒ ('c :: enum ⇒ 'a) ⇒ bool" where
  "is_padded_block bl f =
     (∃k. k ≥ 1 ∧ k < length (enum_class.enum :: 'c list)
       ∧ (∀x. c_idx x < k ⟶ f x ≠ bl)
       ∧ (∀x. c_idx x ≥ k ⟶ f x = bl))"

text ‹Encoder-canonical block: pure or trailing-padded.  The
  validation phase accepts only blocks satisfying this
  predicate; non-canonical blocks (blanks scattered in
  non-trailing positions) route the input to ‹r_M'›.›

definition is_canonical_block ::
  "'a ⇒ ('c :: enum ⇒ 'a) ⇒ bool" where
  "is_canonical_block bl f = (is_pure_block bl f ∨ is_padded_block bl f)"

text ‹Sequence-level encoder-canonicity: the input ‹w› is
  well-formed (= in the encoder image) iff every block is
  pure, *except possibly the last* which may also be padded.
  Per block encoder-canonicity (‹is_canonical_block›) is
  necessary but not sufficient — a sequence with a padded
  block followed by anything else is per-cell canonical but
  not in the encoder image.

  The validation phase enforces exactly this distinction: VFwd
  reject fires on non-canonical cells; VFwdPad reject fires on
  any non-‹bl_block› cell after a padded block.›

definition ae_input_well_formed ::
  "'a ⇒ ('c :: enum ⇒ 'a) list ⇒ bool" where
  "ae_input_well_formed bl w ⟷
     (∀s. s < length w ⟶
        (is_pure_block bl (w ! s)
         ∨ (s = length w - 1 ∧ is_padded_block bl (w ! s))))"

end