Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docs for compose #1196

Merged
merged 11 commits into from
May 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/source/python_tutorials/fsa_algo/code/compose1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import k2
s = '''
0 1 1 1 0
1 2 2 2 0
2 3 -1 -1 0
3
'''

a_fsa = k2.ctc_topo(max_token=2, modified=False)
b_fsa = k2.Fsa.from_str(s, acceptor=False)
c_fsa = k2.compose(a_fsa, b_fsa)

a_fsa.draw('a_fsa_compose.svg', title='a_fsa')
b_fsa.draw('b_fsa_compose.svg', title='b_fsa')
c_fsa.draw('c_fsa_compose.svg', title='c_fsa')
15 changes: 15 additions & 0 deletions docs/source/python_tutorials/fsa_algo/code/compose2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import k2
s = '''
0 1 1 1 0
1 2 2 2 0
2 3 -1 -1 0
3
'''

a_fsa = k2.ctc_topo(max_token=2, modified=False)
b_fsa = k2.Fsa.from_str(s, acceptor=False)
c_fsa = k2.compose(a_fsa, b_fsa, treat_epsilons_specially=False)

a_fsa.draw('a_fsa_compose2.svg', title='a_fsa')
b_fsa.draw('b_fsa_compose2.svg', title='b_fsa')
c_fsa.draw('c_fsa_compose2.svg', title='c_fsa')
16 changes: 16 additions & 0 deletions docs/source/python_tutorials/fsa_algo/code/compose3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import k2
s = '''
0 1 1 1 0
1 2 2 2 0
2 3 -1 -1 0
3
'''

a_fsa = k2.ctc_topo(max_token=2, modified=False)
b_fsa = k2.Fsa.from_str(s, acceptor=False)
b_fsa = k2.add_epsilon_self_loops(b_fsa)
c_fsa = k2.compose(a_fsa, b_fsa, treat_epsilons_specially=False)

a_fsa.draw('a_fsa_compose3.svg', title='a_fsa')
b_fsa.draw('b_fsa_compose3.svg', title='b_fsa')
c_fsa.draw('c_fsa_compose3.svg', title='c_fsa')
103 changes: 101 additions & 2 deletions docs/source/python_tutorials/fsa_algo/fsa_algo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,109 @@ using :func:`k2.add_epsilon_self_loops` with

.. NOTE::

- :func:`k2.intersect` supports **ONLY** CPU
- :func:`k2.intersect` works **ONLY** on CPU when ``treat_epsilons_specially=True``.
When ``treat_epsilons_specially=False`` and both a_fsa and b_fsa are on GPU, then this function works on GPU;
in this case, the two input FSAs do not need to be arc sorted.
- autograd is also supported.
- Its input can be either a single FSA or a FsaVec.
- The input FSAs have to be arc sorted.
- The input FSAs have to be arc sorted when ``treat_epsilons_specially=True``.

compose
~~~~~~~

The composition is a straightforward generalization of the intersection from acceptors to transducers.
The following is an example of :func:`k2.compose`.

.. literalinclude:: ./code/compose1.py
:caption: Example code for :func:`k2.compose`
:language: python
:lines: 2-

The outputs are shown below

.. figure:: images/a_fsa_compose.svg
:alt: a_fsa
:align: center
:figwidth: 600px

.. figure:: images/b_fsa_compose.svg
:alt: b_fsa
:align: center
:figwidth: 600px

.. figure:: images/c_fsa_compose.svg
:alt: c_fsa
:align: center
:figwidth: 600px

:func:`k2.compose` has an optional argument ``treat_epsilons_specially``.
Its default value is `True`. If it is set to `False`, then the label `0`
is treated as a normal label. The following is an example setting
``treat_epsilons_specially`` to `False`.

.. literalinclude:: ./code/compose2.py
:caption: Example code for :func:`k2.compose` with ``treat_epsilons_specially=False``
:language: python
:lines: 2-

The outputs are shown below

.. figure:: images/a_fsa_compose2.svg
:alt: a_fsa
:align: center
:figwidth: 600px

.. figure:: images/b_fsa_compose2.svg
:alt: b_fsa
:align: center
:figwidth: 600px

.. figure:: images/c_fsa_compose2.svg
:alt: c_fsa
:align: center
:figwidth: 600px

Note that ``c_fsa`` contains a single path
when ``treat_epsilons_specially`` is `False`.

:func:`k2.add_epsilon_self_loops` can be used to add epsilon self loops
to an FSA when ``treat_epsilons_specially`` is `False` but you
want to treat them specially. The following is an example
using :func:`k2.add_epsilon_self_loops` with
``treat_epsilons_specially == False``.

.. literalinclude:: ./code/compose3.py
:caption: :func:`k2.intersect` with ``treat_epsilons_specially=False`` and :func:`k2.add_epsilon_self_loops`
:language: python
:lines: 2-

.. figure:: images/a_fsa_compose3.svg
:alt: a_fsa
:align: center
:figwidth: 600px

.. figure:: images/b_fsa_compose3.svg
:alt: b_fsa
:align: center
:figwidth: 600px

.. figure:: images/c_fsa_compose3.svg
:alt: c_fsa
:align: center
:figwidth: 600px

Note that ``c_fsa`` contains more than one paths
even if ``treat_epsilons_specially`` is `False`
since we have added epsilon self loops to `b_fsa`.

.. NOTE::

- :func:`k2.compose` works **ONLY** on CPU when ``treat_epsilons_specially=True``.
When ``treat_epsilons_specially=False`` and both a_fsa and b_fsa are on GPU, then this function works on GPU;
in this case, the two input FSAs do not need to be arc sorted.
- autograd is also supported.
- Its input can be either a single FSA or a FsaVec.
- The input FSAs have to be arc sorted when ``treat_epsilons_specially=True``.

connect
~~~~~~~
Expand Down
123 changes: 123 additions & 0 deletions docs/source/python_tutorials/fsa_algo/images/a_fsa_compose.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading