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

Clarify some comments in rm_epsilon; fix possible bug there. #965

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
8 changes: 3 additions & 5 deletions k2/csrc/rm_epsilon.cu
Original file line number Diff line number Diff line change
Expand Up @@ -769,17 +769,15 @@ void ComputeEpsilonClosure(FsaVec &epsilon_fsa, FsaVec *closure_fsa,
// since thanks to sorting the order is deterministic).
Array1<Arc> epsilon_fsa_arcs = epsilon_fsa.values;
ComputeEpsilonClosureOneIter(epsilon_fsa, closure_fsa, arc_map);
Array1<Arc> closure_fsa_arcs = closure_fsa->values;
// note function `Equal` for Array1 requires the input two arrays have the
// same size.
while (epsilon_fsa_arcs.Dim() != closure_fsa_arcs.Dim() ||
!Equal(epsilon_fsa_arcs, closure_fsa_arcs)) {
epsilon_fsa_arcs = closure_fsa_arcs;
while (epsilon_fsa_arcs.Dim() != closure_fsa->values.Dim() ||
!Equal(epsilon_fsa_arcs, closure_fsa->values)) {
epsilon_fsa_arcs = closure_fsa->values;
FsaVec cur_iter_closure_fsa;
Ragged<int32_t> cur_iter_arc_map;
ComputeEpsilonClosureOneIter(*closure_fsa, &cur_iter_closure_fsa,
&cur_iter_arc_map);
closure_fsa_arcs = cur_iter_closure_fsa.values;
*closure_fsa = cur_iter_closure_fsa;
*arc_map = ComposeArcMaps(*arc_map, cur_iter_arc_map);
}
Expand Down
37 changes: 25 additions & 12 deletions k2/csrc/rm_epsilon.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace k2 {

We keep the original numbering of the states. We'll use capital letters for
sets of arcs. Note: epsilon self-loops can be discarded whenever they appear
if their score is <= 0; if there is scores is >0 we can abort the algorithm
if their score is <= 0; if self-loop scores are >0 we can abort the algorithm
because it would imply that the FSA has some paths with infinite score but
finite number of real symbols.

Expand All @@ -60,8 +60,13 @@ namespace k2 {
uses of parentheses.
P = set of arcs that arises from combination of arcs e in C_p with all arcs in N
that enter the source-state of e, i.e. arc-combinations [n,e].
** Note: unfortunately I have chosen the same letter P to mean this set of
arcs, and also paths. You can figure out from the context which is meant. **
Q = set of arcs that arises from combination of arcs e in C_p with all arcs in F
that enter the source-state of e. i.e. from arc-combinations [f,e]
that enter the source-state of e. i.e. from arc-combinations [f,e]. [Note,
we made a choice here, about how to generate these "second-order" arcs;
we could have let Q be the combination [e,p] of arcs
p in P with preceding arcs e in C_f].

At the start of the algorithm we have the set of arcs
N u E (u means union).
Expand All @@ -83,23 +88,26 @@ namespace k2 {
weight and symbol

The final stage is to remove C_f and C_p, leaving us with
U u F u P u Q
N u F u P u Q
which is epsilon-free. We need to demonstrate that we can remove C_f and C_p
while preserving equivalence. This is the not-quite-so-trivial part of the proof.
Let A be the FSA containing arcs
Let A be the following FSA, as expressed as a set of arcs [treat start-state and
final-state as given].

N u C_f u C_p u F u P u Q
A = N u C_f u C_p u F u P u Q

and B be the FSA containing arcs
and B be the following FSA, again as a set of arcs:

U u F u P u Q.
B = N u F u P u Q.

We show that B and A are equivalent by showing that for any path in A that has
at least one epsilon arc, there is a path in B with the same "real" symbol sequence
(i.e. after removing epsilons) and a score that is at least as large. We
(i.e. after removing epsilons) and a score that is at least as large [and, of course,
the same begin and end state]. We
show this inductively by demonstrating that for any path P in A that has at
least one epsilon, there is a path P' in A that satisfies the following properties:

- P' has the same begin and end state as P
- The score of P' is >= the score of P
- P' has the same real symbol-sequence as P (i.e. the same sequence after
removing epsilons)
Expand All @@ -119,10 +127,11 @@ namespace k2 {
mentioned above.

(i) First imagine that P has two successive epsilon arcs, from states a->b and
b->c. These arcs must both be in either C_f or C_p and hence in C. But because C is the
b->c. Each of these arcs must be in either C_f or C_p, and hence in C. But because C is the
result of epsilon closure there must be an epsilon from a->c with a score at
least as great as the sum of the original two paths' scores; so we can reduce the
number of epsilons by one.
number of epsilons by one, i.e. we can find a path like P but with one fewer
epsilon.

[[Note regarding epsilon-loops: if a and c are the same state, there are two
choices: if the score is <=0 then we can remove the epsilon from our path
Expand All @@ -131,7 +140,9 @@ namespace k2 {
which is equivalent to infinite score, which is invalid.]]

We can use (i) as needed until there are no successive epsilons, so the following
arguments will consider only isolated epsilons. Note on terminology: we use
arguments will consider paths that lack successive epsilons.

Note on terminology: we use
letters a,b,c,d for epsilon arcs below.

(ii) Consider an epsilon-arc a in C_f. This must be followed by a non-epsilon
Expand All @@ -145,7 +156,9 @@ namespace k2 {
argument (i); this leaves us with [c,n], which is
case (b) above, i.e. the same number of epsilons
but one fewer implicit epsilon.
- following arc p is in P -> there was originally a pair [n,b] from which
- following arc p is in P [note, this refers to the set of arcs P, not the path
P, sorry for confusion of letters] ->
there was originally a pair [n,b] from which
p was constructed, where b is in C_p; and there is an
arc f in F to which [a,n] was expanded;
and an arc q in Q to which [f,b] was expanded; so
Expand Down