Subsequential Functions and Finite-State Transducers #
A function f : List α → List β is subsequential when it is computed by a
deterministic finite-state transducer with state-based final output
[Moh97]. Subsequential functions form a proper subclass of the rational
functions (the functional regular relations).
The class has left and right variants according to scan direction; the two
are isomorphic under input/output reversal (f is right-subsequential iff
List.reverse ∘ f ∘ List.reverse is left-subsequential).
Main definitions #
SFST α β σ: a deterministic FST with statesσ, input alphabetα, output alphabetβ, a total output-emitting transition, and a state-indexedfinalOutputemitted on termination.SFST.run,SFST.runRight: the left-to-right and right-to-left passes.IsLeftSubsequential f,IsRightSubsequential f:fis computed by some finite-stateSFSTscanning in that direction.IsSubsequential d f: direction-parameterised umbrella over the two.
Main theorems #
IsLeftSubsequential.comp,IsRightSubsequential.comp,IsSubsequential.comp: subsequential functions are closed under composition (Schützenberger–Choffrut, [Moh97]) — the fact that makes the weakly-deterministic class well-defined.isRightSubsequential_iff_left_reverse: the left and right classes are isomorphic via reverse-conjugation.
Implementation notes #
SFST models the total subsequential functions: step is total, so run
is a total function on List α. Partial subsequential functions can be encoded
by adding a sink state.
TODO #
A subsequential finite-state transducer: a deterministic FST with state
space σ, input alphabet α, output alphabet β, and state-final outputs
[Moh97]. The transition step is total, so the machine computes a total
function List α → List β.
- start : σ
Starting state.
- step : σ → α → σ × List β
Total deterministic transition: move to a next state and emit a (possibly empty) output block.
- finalOutput : σ → List β
Output emitted on terminating in a given state.
Instances For
T.runFrom s x runs T from state s, concatenating each step's output
block and finally T.finalOutput of the terminating state.
Equations
Instances For
The relationship between runFrom and runOnList: runFrom is
runOnList followed by appending the final-state output.
runFrom distributes over input concatenation: walking on xs ++ ys
equals walking the prefix via runOnList (no final emission yet), then
running runFrom from the resulting state on ys (which DOES include
the final emission).
State-space transfer #
Transferring an SFST along a state-space equivalence preserves its
run function. The headline use case is bringing a universe-polymorphic
state down to Fin n (universe Type 0) via Fintype.equivFin, which
lets the universe-polymorphic constructions in ISL.lean / OSL.lean
witness the Type 0-state existential of IsLeftSubsequential /
IsRightSubsequential.
Transfer an SFST along a state-space equivalence σ ≃ τ. Replaces
each state-valued field with the corresponding τ-valued one via the
equivalence.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The transferred SFST computes the same string function as the original.
Composition #
Subsequential functions are closed under composition ([Moh97], back to Schützenberger and Choffrut). This is the load-bearing fact that makes the weakly-deterministic class (compositions of two subsequentials) well-defined.
Construction: the product SFST with state σ_f × σ_g threads both
machines, where the consumer FST T_g walks over each output block
emitted by the producer FST T_f.
Compose two SFSTs: T_f : SFST α β σ_f and T_g : SFST β γ σ_g
yield an SFST with state σ_f × σ_g whose run computes T_g.run ∘ T_f.run.
State threading: each input symbol triggers one T_f step (which may
emit a multi-symbol β block); T_g then walks through that block via
runOnList, advancing its state. The combined finalOutput runs
T_f.finalOutput through T_g (including T_g's own final flush).
Equations
- One or more equations did not get rendered due to their size.
Instances For
compose's runFrom agrees with sequential runFroms: the product
SFST compose Tg Tf walks Tf over the input from s.1, threading
each emitted block through Tg from s.2.
Subsequential classification predicates #
The witness-style predicates below follow mathlib's Language.IsRegular
shape: the state space σ is existentially quantified at Type with a
Fintype σ instance, while the alphabets α β are universe-polymorphic
at Type*. The Fintype constraint matches the source literature
([Moh97]), where every SFST has finitely many states by definition,
and also lets the universe parameter for state collapse cleanly without
universe declarations or ULift coercions.
Constructor lemmas (SFST.isLeftSubsequential, SFST.isRightSubsequential
below) hide the existential-over-types shape so future redesigns
(e.g. to a Myhill–Nerode finite-index characterization with σ ≃ Fin n)
won't touch consumer sites. Downstream ISL/OSL inclusion theorems take
[Fintype α] / [Fintype β] and use a bounded-window finite state to
witness the predicate (Function/{ISL,OSL}.lean).
A function f : List α → List β is left-subsequential iff some
SFST with a finite state space computes it via left-to-right scan. The
Fintype σ constraint matches the source literature [Moh97].
Equations
- Subregular.IsLeftSubsequential f = ∃ (σ : Type) (x : Fintype σ) (T : Subregular.SFST α β σ), T.run = f
Instances For
A function f : List α → List β is right-subsequential iff some
SFST with a finite state space computes it via right-to-left scan
(runRight).
Equations
- Subregular.IsRightSubsequential f = ∃ (σ : Type) (x : Fintype σ) (T : Subregular.SFST α β σ), T.runRight = f
Instances For
A function f : List α → List β is subsequential in direction d
iff some finite-state SFST computes it via the corresponding scan
direction. Direction-parameterised umbrella; concrete claims should
typically use one of IsLeftSubsequential / IsRightSubsequential
directly for clarity.
Equations
Instances For
Every finite-state SFST witnesses IsLeftSubsequential for its run.
Consumers use T.isLeftSubsequential instead of building the existential
quadruple, so a redesign of IsLeftSubsequential touches only this lemma. The
arbitrary-Type* state is brought down to Fin (Fintype.card σ) via
SFST.transferEquiv and Fintype.equivFin.
Every finite-state SFST witnesses IsRightSubsequential for its runRight.
See SFST.isLeftSubsequential for rationale.
A function is Right-Subsequential iff its reverse-conjugate is
Left-Subsequential: the two classes are isomorphic via the involution
f ↦ List.reverse ∘ f ∘ List.reverse.
A left-subsequential function has bounded delay ([Moh97]): on any input u it
has already emitted a prefix of f u shared with f (u ++ v) for every continuation
v, withholding at most the longest state-final output.
f is not left-subsequential if for every N some images f u and f (u ++ v)
disagree more than N positions before the end of f u: the working form of
bounded_delay for impossibility proofs (e.g. unbounded tonal plateauing,
[Jar16]).
Subsequential functions are closed under composition ([Moh97],
originally Schützenberger and Choffrut) — the load-bearing fact that makes
the weakly-deterministic class (composition of two subsequential functions
reading from opposite directions) well-defined. The product state σf × σg
inherits Fintype from Mathlib.Data.Fintype.Prod.
Right-Subsequential closure under composition, derived from the Left-
counterpart via isRightSubsequential_iff_left_reverse: the reverse-conjugate
of a composition is the composition of reverse-conjugates.
Direction-parameterised composition closure: both Left- and
Right-Subsequential functions are closed under composition. Delegates to
IsLeftSubsequential.comp / IsRightSubsequential.comp.