Lab 1: Basic FST Manipulation

There are three classes used in Lab 1: _MutableFst, the main class for a “mutable” FST (ie. one that can be dynamically modified in the code); Arc, which is the arc object used to connect states in an FST; and SymbolTable, which maps input or output strings to the integer IDs used as arc labels by OpenFst.

Note

Please go to the github repo to view the jupyter notebook file for this lab.

openfst_python.pywrapfst.SymbolTable([name])

Mutable SymbolTable class.

openfst_python.pywrapfst._MutableFst

(No constructor.)

openfst_python.pywrapfst.Arc(ilabel, olabel, ...)

This class represents an arc while remaining agnostic about the underlying arc type.

SymbolTable

First, let’s have a look at how to create a SymbolTable.

>>> # Here is an example of instantiating a SymbolTable
>>> import openfst_python as fst
>>> st = fst.SymbolTable()

You will use two main methods of the class:

class openfst_python.pywrapfst.SymbolTable(name='<unspecified>')

Mutable SymbolTable class.

This class wraps the library SymbolTable and exposes both const (i.e., access) and non-const (i.e., mutation) methods of wrapped object.

Unlike other classes in the hierarchy, it has a working constructor and can be used to programmatically construct a SymbolTable in memory.

Args:

name: An optional string indicating the table’s name.

add_symbol(self, symbol, key=NO_SYMBOL)

Adds a symbol to the table and returns the index.

This method adds a symbol to the table. The caller can optionally specify a non-negative integer index for the key.

Args:

symbol: A symbol string. key: An index for the symbol; if not specified, the next index will be

used.

Returns:

The integer key of the new symbol.

find(self, key)

Given a symbol or index, finds the other one.

This method returns the index associated with a symbol key, or the symbol associated with a index key.

Args:

key: Either a string or an index.

Returns:
If the key is a string, the associated index or NO_LABEL if not found; if

the key is an integer, the associated symbol or an empty string if not found.

To add a new symbol to a symbol table,

>>> idx = st.add_symbol('a')
>>> idx
>>> 0 # as you can see above, the method, add_symbol, returns the index corresponding to the
>>>   # label 'a', because this is the first label we add into the symbol table.
>>> idx = st.add_symbol('b')
>>> idx
>>> 1 # this time it returns 1, as 'b' is the second label we add into the symbol table

To find the index corresponding to a label already in the symbol table, we can use the method SymbolTable.find()

>>> idx = st.find('a')
>>> idx
>>> 0 # the label 'a' is in the symbol table, so it returns its index, and here it is 0.
>>> idx = st.find('c')
>>> idx
>>> -1 # the label 'c' is not in the symbol table, so it returns NO_SYMBOL value, which here is -1 by default.

To recap, the SymbolTable is just a mapping between the text symbol (string) and the internal index used by OpenFst (int).

Fst

Now, let’s create an FST object.

>>> f = fst.Fst()
>>> type(f)
>>> <class 'pywrapfst._MutableFst'>

To create an FST object, we use fst.Fst(), but the instantiated object f is an instance of the class pywrapfst._MutableFst. “Mutable” means that returned FST can be dynamically manipulated in the code.

Here are some frequently used class method used in the labs.

class openfst_python.pywrapfst._MutableFst

(No constructor.)

Mutable FST class, wrapping MutableFstClass.

This class extends _Fst by adding mutation operations.

add_arc(self, state, arc)

Adds a new arc to the FST and return self.

Args:

state: The integer index of the source state. arc: The arc to add.

Returns:

self.

Raises:

FstIndexError: State index out of range. FstOpdexError: Incompatible or invalid weight type.

See also: add_state.

add_state(self)

Adds a new state to the FST and returns the state ID.

Returns:

The integer index of the new state.

See also: add_arc, set_start, set_final.

set_final(self, state, weight)

Sets the final weight for a state.

Args:

state: The integer index of a state. weight: A Weight or weight string indicating the desired final weight; if

omitted, it is set to semiring One.

Returns:

self.

Raises:

FstIndexError: State index out of range. FstOpError: Incompatible or invalid weight.

See also: set_start.

set_input_symbols(self, syms)

Sets the input symbol table.

Passing None as a value will delete the input symbol table.

Args:

syms: A SymbolTable.

Returns:

self.

See also: set_output_symbols.

set_output_symbols(self, syms)

Sets the output symbol table.

Passing None as a value will delete the output symbol table.

Args:

syms: A SymbolTable.

Returns:

self.

See also: set_input_symbols.

set_start(self, state)

Sets a state to be the initial state state.

Args:

state: The integer index of a state.

Returns:

self.

Raises:

FstIndexError: State index out of range.

See also: set_final.

Here are some basic examples.

To add a new state in the Fst,

>>> new_state = f.add_state()
>>> new_state
>>> 0 # add_state() returns the state index (int) for the state (new_state) we just added.

To set the state we just added (new_state) as the start state for the Fst,

>>> f.set_start(new_state)

Let’s add another state and set it as the final state for the Fst,

>>> another_new_state = f.add_state()
>>> f.set_final(another_new_state)

To set a SymbolTable, say input_symbols, as the input symbol table for our Fst,

>>> f.set_input_symbols(input_symbols)

To set a SymbolTable, say output_symbols, as the output symbol table for our Fst,

>>> f.set_output_symbols(output_symbols)

The remaining method, add_arc() will be mentioned in the following section together with fst.Arc.

Arc

The final class we’ll inclue here is fst.Arc.

class openfst_python.pywrapfst.Arc(ilabel, olabel, weight, nextstate)

This class represents an arc while remaining agnostic about the underlying arc type. Attributes of the arc can be accessed or mutated, and the arc can be copied.

Attributes:

ilabel: The input label. olabel: The output label. weight: The arc weight. nextstate: The destination state for the arc.

Let’s see a simple example.

>>> import openfst_python as fst
>>> f = fst.Fst() # instantiate an fst._MutableFst object
>>> # Let's add two states into f.
>>> state1 = f.add_state()
>>> state2 = f.add_state()
>>>
>>> # Here we instantiate an arc with 0 as the index of the input label, 1 as the index of the
>>> # output label, and a weight of None (we will talk more about weights in Lab 2), going to
>>> # state2 as the next state
>>> arc = fst.Arc(0, 1, None, state2)
>>> f.add_arc(state1, arc) # Add the arc to our fst from state1