Interactive Notes on Finite-State Machine
· 3 min read
A word on language
Mirroring the daily meaning of the word, in formal language theory, an alphabet is a finite1 set of characters. A string over the alphabet is a tuple in in which we write simply as . A string in has length , denoted . The set of all strings of all lengths over the alphabet is the Kleene closure of and denoted ; symbolically,
We define , where is the empty string, the only string having zero length. A language over is a subset of . As an example of a frequently-seen language, the set of all binary strings is .
Given strings and over , the concatenation of and , denoted or just , is the string produced by appending to :
Note that for any string .
type Letter = string | symbol;
type Str<L extends Letter> = Iterable<L>;
Finite-state machine
A finite-state machine (FSM)2 is specified through five elements, as follows:
where
- is the set of ’s states,
- is ’s input alphabet,
- is ’s transition function,
- is ’s initial state,
- is the set of ’s final states.
Mechanistically, an FSM can be thought of as a machine that repeatedly receives a character from an alphabet and changes its internal status accordingly. Though the above specification does not mention output, we can regard as being able to output YES or NO, depending on whether its state is one of the final states.
Naturally, we can extend the transition function to accept an arbitrary string over in an inductive manner: for and , we define
The function can receive as input any (nonempty) string over . We also let —by reading no input, the machine does not change its state. We overload to mean and assume the transition function can take arbitrary strings as input. Note that .
The FSM is said to accept a string if . In other words, the machine “output” YES when it accepts the input string and NO otherwise. The set of strings that accepts is the language accepted or recognized by .
type State = string | symbol;
class FSM<S extends State, L extends Letter> {
state: S;
initialState: S;
transition: (input: Str<L>) => void;
finalStates: Set<S>;
constructor(
initialState: S,
finalStates: Set<S>,
t: (s: S, l: L) => S
) {
this.state = initialState;
this.initialState = initialState;
this.finalStates = finalStates;
this.transition = (input: Str<L>) => {
for (const l of input) {
this.state = t(this.state, l);
}
}
}
}