Subsequential functions and finite-state transducers #
A subsequential transducer is a deterministic state machine which maps strings to strings, emitting a block of output for each input symbol and a final block determined by the ending state [Sch77] [Moh97]. The functions so computed — subsequential, with left- and right-scan variants — form a proper subclass of the rational functions [FR16].
We show that each class is closed under composition, that the two are isomorphic under
reverse-conjugation, and that both contain the Mealy-computable functions; a
left-subsequential function withholds at most a bounded output suffix
(bounded_delay).
Like DFA, this definition allows for machines with infinite states; the
classification predicates require a Fintype instance.
Main definitions #
SubsequentialTransducer σ α β: transducer over alphabetsα,βand statesσSubsequentialTransducer.run/SubsequentialTransducer.runRight: the two passesSubsequentialTransducer.ofWindow: the sliding-window transducerIsLeftSubsequential f,IsRightSubsequential f,IsSubsequential d f: some finite-state transducer computesfin the given scan direction
Implementation notes #
The name follows [Cho77] and [Moh97]: sequential without state-final
output, subsequential with. [Sak09] calls this class sequential (and
the empty-flush case pure sequential), flagging his usage as unconventional (cf.
[BR99b]); we keep the Choffrut spelling. Mealy is the
letter-to-letter case.
step is total, so only the total subsequential functions are modelled — a sink
state does not recover partiality — and the initial-output function of
[Sak09] is omitted. There are two disjoint sets of simp lemmas, one for
run and another for runFrom; switch from the former to the latter via simp [run].
TODO #
- Choffrut's theorem [Cho77]: a rational function is subsequential iff it has
bounded variation, decidably via twinning;
bounded_delayis far weaker. - Canonical forms and minimization; two-way transducers; p-subsequential functions.
A subsequential finite-state transducer is a set of states (σ), a starting state
(start), a transition function (step), a per-symbol output function (output) and
a state-final output (finalOutput).
- start : σ
Starting state.
- step : σ → α → σ
Transition function.
- output : σ → α → List β
The block of output symbols emitted on reading an input symbol in a state.
- finalOutput : σ → List β
Output emitted on terminating in a state.
Instances For
Equations
- One or more equations did not get rendered due to their size.
T.stateAfter s x is the state reached from s after consuming the input x.
Equations
- T.stateAfter s = List.foldl T.step s
Instances For
T.emitted s x is the output emitted while consuming the input x from the
state s, without the final flush.
Equations
Instances For
T.runFrom s x runs T on the input x from the state s: the emitted output
followed by the final flush.
Equations
- T.runFrom s xs = T.emitted s xs ++ T.finalOutput (T.stateAfter s xs)
Instances For
T.runRight x runs T right-to-left on the input x.
Instances For
Transport along state equivalences #
Transport a transducer along an equivalence on states.
Equations
- One or more equations did not get rendered due to their size.
Instances For
map as an equivalence of machines.
Equations
- SubsequentialTransducer.reindex g = { toFun := SubsequentialTransducer.map g, invFun := SubsequentialTransducer.map g.symm, left_inv := ⋯, right_inv := ⋯ }
Instances For
Composition #
T₂.comp T₁ feeds each output block of T₁ to T₂ — the classical product
construction [Moh97] — computing T₂.run ∘ T₁.run.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Window transducers #
The transducer whose state is a window of the last n accumulated symbols. out
emits from the window and the current symbol; upd chooses what the window accumulates
(fun _ x => [x] for the input, out for the output).
Equations
- One or more equations did not get rendered due to their size.
Instances For
The window recursion computed by ofWindow; each step emits out and extends the
window by upd, truncated to length n.
Equations
- SubsequentialTransducer.windowRun n out upd x✝ [] = []
- SubsequentialTransducer.windowRun n out upd x✝ (x_2 :: xs) = out x✝ x_2 ++ SubsequentialTransducer.windowRun n out upd ((x✝ ++ upd x✝ x_2).rtake n) xs
Instances For
Letter-to-letter machines as block transducers #
A Mealy machine is a SubsequentialTransducer emitting singleton blocks with an
empty final flush; LetterToLetter witnesses the singleton blocks, and the two views
are mutually inverse.
View a Mealy machine as a block SubsequentialTransducer: singleton outputs,
empty flush.
Equations
Instances For
A witness that every output block of T is a singleton, named by cell.
- cell : σ → α → β
The single symbol emitted at a cell.
Every output block is that singleton.
Instances For
Extract a witness from a bound on block lengths.
Equations
- SubsequentialTransducer.LetterToLetter.ofLength hs = { cell := fun (s : σ) (x : α) => (T.output s x).head ⋯, output_eq := ⋯ }
Instances For
The Mealy machine emitting each cell's symbol.
Instances For
A letter-to-letter transducer with no final flush is the block form of its Mealy view.
A finite-state letter-to-letter transducer with no final flush computes a Mealy-computable function.
The canonical witness that a Mealy machine's block form is letter-to-letter.
Equations
- T.letterToLetter = { cell := T.output, output_eq := ⋯ }
Instances For
Subsequential classification predicates #
A function f : List α → List β is left-subsequential if some finite-state
transducer computes it via left-to-right scan [Moh97].
Equations
- IsLeftSubsequential f = ∃ (σ : Type) (x : Fintype σ) (T : SubsequentialTransducer σ α β), T.run = f
Instances For
A function f : List α → List β is right-subsequential if its reverse-conjugate
is left-subsequential — equivalently, some finite-state transducer computes it via
right-to-left scan (isRightSubsequential_iff).
Equations
Instances For
A function f : List α → List β is subsequential in direction d if some
finite-state SubsequentialTransducer computes it via the corresponding scan direction.
Equations
Instances For
The universe-polymorphic form of IsLeftSubsequential.
The universe-polymorphic form of IsRightSubsequential, in the runRight shape.
Every finite-state transducer computes a left-subsequential function, whatever the universe of its state type.
Every finite-state transducer computes a right-subsequential function via
runRight.
A Mealy-computable function is left-subsequential: Mealy.toSubsequentialTransducer
presents a Mealy machine as a block transducer emitting singleton blocks.
A function is right-subsequential iff its reverse-conjugate is left-subsequential —
definitionally: the right class is the List.revConj-image of the left class.
A left-subsequential function withholds at most the longest state-final output:
f u and f (u ++ v) share a prefix covering all but boundedly many symbols of f u.
Much weaker than [Cho77]'s bounded-variation characterization — this compares
u only with its own extensions.
The coordinate form of bounded_delay: coordinates of f u more than N
positions before its end are stable under extending the input.
A length-preserving left-subsequential function is oblivious to input beyond a fixed
margin of each output coordinate: the delay bound of exists_getElem?_append_eq caps how
far to the right an output coordinate can look.
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 contrapositive of
bounded_delay.
Left-subsequential functions are closed under composition, by the classical product construction [Moh97].
Right-subsequential closure under composition: conjugate the left closure.
Subsequential functions are closed under composition in either scan direction.